~pvigo/+junk/owncloud-14.04

« back to all changes in this revision

Viewing changes to usr/share/owncloud/apps/files_external/3rdparty/smb4php/smb.php

  • Committer: Pablo Vigo
  • Date: 2014-12-15 13:36:46 UTC
  • Revision ID: pvigo@xtec.cat-20141215133646-7d6it90e1dbsijc2
2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
###################################################################
3
 
# smb.php
4
 
# This class implements a SMB stream wrapper based on 'smbclient'
5
 
#
6
 
# Date: lun oct 22 10:35:35 CEST 2007
7
 
#
8
 
# Homepage: http://www.phpclasses.org/smb4php
9
 
#
10
 
# Copyright (c) 2007 Victor M. Varela <vmvarela@gmail.com>
11
 
#
12
 
# This program is free software; you can redistribute it and/or
13
 
# modify it under the terms of the GNU General Public License
14
 
# as published by the Free Software Foundation; either version 2
15
 
# of the License, or (at your option) any later version.
16
 
#
17
 
# This program is distributed in the hope that it will be useful,
18
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 
# GNU General Public License for more details.
21
 
#
22
 
# Addition 17/12/2012 Frank Karlitschek (frank@owncloud.org)
23
 
# On the official website http://www.phpclasses.org/smb4php the
24
 
# license is listed as LGPL so we assume that this is
25
 
# dual-licensed GPL/LGPL
26
 
###################################################################
27
 
 
28
 
define ('SMB4PHP_VERSION', '0.8');
29
 
 
30
 
###################################################################
31
 
# CONFIGURATION SECTION - Change for your needs
32
 
###################################################################
33
 
 
34
 
define ('SMB4PHP_SMBCLIENT', 'smbclient');
35
 
define ('SMB4PHP_SMBOPTIONS', 'TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_RCVBUF=8192 SO_SNDBUF=8192');
36
 
define ('SMB4PHP_AUTHMODE', 'arg'); # set to 'env' to use USER enviroment variable
37
 
 
38
 
###################################################################
39
 
# SMB - commands that does not need an instance
40
 
###################################################################
41
 
 
42
 
$GLOBALS['__smb_cache'] = array ('stat' => array (), 'dir' => array ());
43
 
 
44
 
class smb {
45
 
 
46
 
        function parse_url ($url) {
47
 
                $pu = parse_url (trim($url));
48
 
                foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
49
 
                        if (! isset($pu[$i])) {
50
 
                                $pu[$i] = '';
51
 
                        }
52
 
                }
53
 
                if (count ($userdomain = explode (';', urldecode ($pu['user']))) > 1) {
54
 
                        @list ($pu['domain'], $pu['user']) = $userdomain;
55
 
                }
56
 
                $path = preg_replace (array ('/^\//', '/\/$/'), '', urldecode ($pu['path']));
57
 
                list ($pu['share'], $pu['path']) = (preg_match ('/^([^\/]+)\/(.*)/', $path, $regs))
58
 
                        ? array ($regs[1], preg_replace ('/\//', '\\', $regs[2]))
59
 
                        : array ($path, '');
60
 
                $pu['type'] = $pu['path'] ? 'path' : ($pu['share'] ? 'share' : ($pu['host'] ? 'host' : '**error**'));
61
 
                if (! ($pu['port'] = intval(@$pu['port']))) {
62
 
                        $pu['port'] = 139;
63
 
                }
64
 
 
65
 
                // decode user and password
66
 
                $pu['user'] = urldecode($pu['user']);
67
 
                $pu['pass'] = urldecode($pu['pass']);
68
 
                return $pu;
69
 
        }
70
 
 
71
 
 
72
 
        function look ($purl) {
73
 
                return smb::client ('-L ' . escapeshellarg ($purl['host']), $purl);
74
 
        }
75
 
 
76
 
 
77
 
        function execute ($command, $purl) {
78
 
                return smb::client ('-d 0 '
79
 
                                . escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
80
 
                                . ' -c ' . escapeshellarg ($command), $purl
81
 
                );
82
 
        }
83
 
 
84
 
        function client ($params, $purl) {
85
 
 
86
 
                static $regexp = array (
87
 
                        '^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip',
88
 
                        'Anonymous login successful' => 'skip',
89
 
                        '^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip',
90
 
                        '^\tSharename[ ]+Type[ ]+Comment$' => 'shares',
91
 
                        '^\t---------[ ]+----[ ]+-------$' => 'skip',
92
 
                        '^\tServer   [ ]+Comment$' => 'servers',
93
 
                        '^\t---------[ ]+-------$' => 'skip',
94
 
                        '^\tWorkgroup[ ]+Master$' => 'workg',
95
 
                        '^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip',
96
 
                        '^\tIPC\\\$(.*)[ ]+IPC' => 'skip',
97
 
                        '^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share',
98
 
                        '^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip',
99
 
                        '([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip',
100
 
                        'Got a positive name query response from ' => 'skip',
101
 
                        '^(session setup failed): (.*)$' => 'error',
102
 
                        '^(.*): ERRSRV - ERRbadpw' => 'error',
103
 
                        '^Error returning browse list: (.*)$' => 'error',
104
 
                        '^tree connect failed: (.*)$' => 'error',
105
 
                        '^(Connection to .* failed)(.*)$' => 'error-connect',
106
 
                        '^NT_STATUS_(.*) ' => 'error',
107
 
                        '^NT_STATUS_(.*)\$' => 'error',
108
 
                        'ERRDOS - ERRbadpath \((.*).\)' => 'error',
109
 
                        'cd (.*): (.*)$' => 'error',
110
 
                        '^cd (.*): NT_STATUS_(.*)' => 'error',
111
 
                        '^\t(.*)$' => 'srvorwg',
112
 
                        '^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip',
113
 
                        '^Job ([0-9]+) cancelled' => 'skip',
114
 
                        '^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files',
115
 
                        '^message start: ERRSRV - (ERRmsgoff)' => 'error'
116
 
                );
117
 
 
118
 
                if (SMB4PHP_AUTHMODE == 'env') {
119
 
                        putenv("USER={$purl['user']}%{$purl['pass']}");
120
 
                        $auth = '';
121
 
                } else {
122
 
                        $auth = ($purl['user'] <> '' ? (' -U ' . escapeshellarg ($purl['user'] . '%' . $purl['pass'])) : '');
123
 
                }
124
 
                if ($purl['domain'] <> '') {
125
 
                        $auth .= ' -W ' . escapeshellarg ($purl['domain']);
126
 
                }
127
 
                $port = ($purl['port'] <> 139 ? ' -p ' . escapeshellarg ($purl['port']) : '');
128
 
                $options = '-O ' . escapeshellarg(SMB4PHP_SMBOPTIONS);
129
 
 
130
 
                // this put env is necessary to read the output of smbclient correctly
131
 
                $old_locale = getenv('LC_ALL');
132
 
                putenv('LC_ALL=en_US.UTF-8');
133
 
                $output = popen ('TZ=UTC '.SMB4PHP_SMBCLIENT." -N {$auth} {$options} {$port} {$options} {$params} 2>/dev/null", 'r');
134
 
                $gotInfo = false;
135
 
                $info = array ();
136
 
                $info['info']= array ();
137
 
                $mode = '';
138
 
                while ($line = fgets ($output, 4096)) {
139
 
                        list ($tag, $regs, $i) = array ('skip', array (), array ());
140
 
                        reset ($regexp);
141
 
                        foreach ($regexp as $r => $t) if (preg_match ('/'.$r.'/', $line, $regs)) {
142
 
                                $tag = $t;
143
 
                                break;
144
 
                        }
145
 
                        switch ($tag) {
146
 
                                case 'skip':    continue;
147
 
                                case 'shares':  $mode = 'shares';     break;
148
 
                                case 'servers': $mode = 'servers';    break;
149
 
                                case 'workg':   $mode = 'workgroups'; break;
150
 
                                case 'share':
151
 
                                        list($name, $type) = array (
152
 
                                                trim(substr($line, 1, 15)),
153
 
                                                trim(strtolower(substr($line, 17, 10)))
154
 
                                        );
155
 
                                        $i = ($type <> 'disk' && preg_match('/^(.*) Disk/', $line, $regs))
156
 
                                                ? array(trim($regs[1]), 'disk')
157
 
                                                : array($name, 'disk');
158
 
                                        break;
159
 
                                case 'srvorwg':
160
 
                                        list ($name, $master) = array (
161
 
                                                strtolower(trim(substr($line,1,21))),
162
 
                                                strtolower(trim(substr($line, 22)))
163
 
                                        );
164
 
                                        $i = ($mode == 'servers') ? array ($name, "server") : array ($name, "workgroup", $master);
165
 
                                        break;
166
 
                                case 'files':
167
 
                                        list ($attr, $name) = preg_match ("/^(.*)[ ]+([D|A|H|S|R]+)$/", trim ($regs[1]), $regs2)
168
 
                                                ? array (trim ($regs2[2]), trim ($regs2[1]))
169
 
                                                : array ('', trim ($regs[1]));
170
 
                                        list ($his, $im) = array (
171
 
                                                explode(':', $regs[6]), 1 + strpos("JanFebMarAprMayJunJulAugSepOctNovDec", $regs[4]) / 3);
172
 
                                        $i = ($name <> '.' && $name <> '..')
173
 
                                                ? array (
174
 
                                                        $name,
175
 
                                                        (strpos($attr,'D') === FALSE) ? 'file' : 'folder',
176
 
                                                        'attr' => $attr,
177
 
                                                        'size' => intval($regs[2]),
178
 
                                                        'time' => mktime ($his[0], $his[1], $his[2], $im, $regs[5], $regs[7])
179
 
                                                )
180
 
                                                : array();
181
 
                                        break;
182
 
                                case 'error':
183
 
                                        if(substr($regs[0],0,22)=='NT_STATUS_NO_SUCH_FILE'){
184
 
                                                return false;
185
 
                                        }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_COLLISION'){
186
 
                                                return false;
187
 
                                        }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_PATH_NOT_FOUND'){
188
 
                                                return false;
189
 
                                        }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_NOT_FOUND'){
190
 
                                                return false;
191
 
                                        }elseif(substr($regs[0],0,29)=='NT_STATUS_FILE_IS_A_DIRECTORY'){
192
 
                                                return false;
193
 
                                        }
194
 
                                        trigger_error($regs[0].' params('.$params.')', E_USER_ERROR);
195
 
                                case 'error-connect':
196
 
                                        // connection error can happen after obtaining share list if
197
 
                                        // NetBIOS is disabled/blocked on the target server,
198
 
                                        // in which case we keep the info and continue
199
 
                                        if (!$gotInfo) {
200
 
                                                return false;
201
 
                                        }
202
 
                        }
203
 
                        if ($i) switch ($i[1]) {
204
 
                                case 'file':
205
 
                                case 'folder':    $info['info'][$i[0]] = $i;
206
 
                                case 'disk':
207
 
                                case 'server':
208
 
                                case 'workgroup': $info[$i[1]][] = $i[0];
209
 
                                $gotInfo = true;
210
 
                        }
211
 
                }
212
 
                pclose($output);
213
 
 
214
 
 
215
 
                // restore previous locale
216
 
                if ($old_locale===false) {
217
 
                        putenv('LC_ALL');
218
 
                } else {
219
 
                        putenv('LC_ALL='.$old_locale);
220
 
                }
221
 
 
222
 
                return $info;
223
 
        }
224
 
 
225
 
 
226
 
        # stats
227
 
 
228
 
        function url_stat ($url, $flags = STREAM_URL_STAT_LINK) {
229
 
                if ($s = smb::getstatcache($url)) {
230
 
                        return $s;
231
 
                }
232
 
                list ($stat, $pu) = array (false, smb::parse_url ($url));
233
 
                switch ($pu['type']) {
234
 
                        case 'host':
235
 
                                if ($o = smb::look ($pu))
236
 
                                        $stat = stat ("/tmp");
237
 
                                else
238
 
                                        trigger_error ("url_stat(): list failed for host '{$pu['host']}'", E_USER_WARNING);
239
 
                                break;
240
 
                        case 'share':
241
 
                                if ($o = smb::look ($pu)) {
242
 
                                        $found = FALSE;
243
 
                                        $lshare = strtolower ($pu['share']);  # fix by Eric Leung
244
 
                                        foreach ($o['disk'] as $s) if ($lshare == strtolower($s)) {
245
 
                                                $found = TRUE;
246
 
                                                $stat = stat ("/tmp");
247
 
                                                break;
248
 
                                        }
249
 
                                        if (! $found)
250
 
                                                trigger_error ("url_stat(): disk resource '{$lshare}' not found in '{$pu['host']}'", E_USER_WARNING);
251
 
                                }
252
 
                                break;
253
 
                        case 'path':
254
 
                                if ($o = smb::execute ('dir "'.$pu['path'].'"', $pu)) {
255
 
                                        $p = explode('\\', $pu['path']);
256
 
                                        $name = $p[count($p)-1];
257
 
                                        if (isset ($o['info'][$name])) {
258
 
                                                $stat = smb::addstatcache ($url, $o['info'][$name]);
259
 
                                        } else {
260
 
                                                trigger_error ("url_stat(): path '{$pu['path']}' not found", E_USER_WARNING);
261
 
                                        }
262
 
                                } else {
263
 
                                        return false;
264
 
//                                      trigger_error ("url_stat(): dir failed for path '{$pu['path']}'", E_USER_WARNING);
265
 
                                }
266
 
                                break;
267
 
                        default: trigger_error ('error in URL', E_USER_ERROR);
268
 
                }
269
 
                return $stat;
270
 
        }
271
 
 
272
 
        function addstatcache ($url, $info) {
273
 
                $url = str_replace('//', '/', $url);
274
 
                $url = rtrim($url, '/');
275
 
                global $__smb_cache;
276
 
                $is_file = (strpos ($info['attr'],'D') === FALSE);
277
 
                $s = ($is_file) ? stat ('/etc/passwd') : stat ('/tmp');
278
 
                $s[7] = $s['size'] = $info['size'];
279
 
                $s[8] = $s[9] = $s[10] = $s['atime'] = $s['mtime'] = $s['ctime'] = $info['time'];
280
 
                return $__smb_cache['stat'][$url] = $s;
281
 
        }
282
 
 
283
 
        function getstatcache ($url) {
284
 
                $url = str_replace('//', '/', $url);
285
 
                $url = rtrim($url, '/');
286
 
                global $__smb_cache;
287
 
                return isset ($__smb_cache['stat'][$url]) ? $__smb_cache['stat'][$url] : FALSE;
288
 
        }
289
 
 
290
 
        function clearstatcache ($url='') {
291
 
                $url = str_replace('//', '/', $url);
292
 
                $url = rtrim($url, '/');
293
 
                global $__smb_cache;
294
 
                if ($url == '') $__smb_cache['stat'] = array (); else unset ($__smb_cache['stat'][$url]);
295
 
        }
296
 
 
297
 
 
298
 
        # commands
299
 
 
300
 
        function unlink ($url) {
301
 
                $pu = smb::parse_url($url);
302
 
                if ($pu['type'] <> 'path') trigger_error('unlink(): error in URL', E_USER_ERROR);
303
 
                smb::clearstatcache ($url);
304
 
                smb_stream_wrapper::cleardircache (dirname($url));
305
 
                return smb::execute ('del "'.$pu['path'].'"', $pu);
306
 
        }
307
 
 
308
 
        function rename ($url_from, $url_to) {
309
 
                $replace = false;
310
 
                list ($from, $to) = array (smb::parse_url($url_from), smb::parse_url($url_to));
311
 
                if ($from['host'] <> $to['host'] ||
312
 
                        $from['share'] <> $to['share'] ||
313
 
                        $from['user'] <> $to['user'] ||
314
 
                        $from['pass'] <> $to['pass'] ||
315
 
                        $from['domain'] <> $to['domain']) {
316
 
                        trigger_error('rename(): FROM & TO must be in same server-share-user-pass-domain', E_USER_ERROR);
317
 
                }
318
 
                if ($from['type'] <> 'path' || $to['type'] <> 'path') {
319
 
                        trigger_error('rename(): error in URL', E_USER_ERROR);
320
 
                }
321
 
                smb::clearstatcache ($url_from);
322
 
                $cmd = '';
323
 
                // check if target file exists
324
 
                if (smb::url_stat($url_to)) {
325
 
                        // delete target file first
326
 
                        $cmd = 'del "' . $to['path'] . '"; ';
327
 
                        $replace = true;
328
 
                }
329
 
                $cmd .= 'rename "' . $from['path'] . '" "' . $to['path'] . '"';
330
 
                $result = smb::execute($cmd, $to);
331
 
                if ($replace) {
332
 
                        // clear again, else the cache will return the info
333
 
                        // from the old file
334
 
                        smb::clearstatcache ($url_to);
335
 
                }
336
 
                return $result !== false;
337
 
        }
338
 
 
339
 
        function mkdir ($url, $mode, $options) {
340
 
                $pu = smb::parse_url($url);
341
 
                if ($pu['type'] <> 'path') trigger_error('mkdir(): error in URL', E_USER_ERROR);
342
 
                return smb::execute ('mkdir "'.$pu['path'].'"', $pu)!==false;
343
 
        }
344
 
 
345
 
        function rmdir ($url) {
346
 
                $pu = smb::parse_url($url);
347
 
                if ($pu['type'] <> 'path') trigger_error('rmdir(): error in URL', E_USER_ERROR);
348
 
                smb::clearstatcache ($url);
349
 
                smb_stream_wrapper::cleardircache (dirname($url));
350
 
                return smb::execute ('rmdir "'.$pu['path'].'"', $pu)!==false;
351
 
        }
352
 
 
353
 
}
354
 
 
355
 
###################################################################
356
 
# SMB_STREAM_WRAPPER - class to be registered for smb:// URLs
357
 
###################################################################
358
 
 
359
 
class smb_stream_wrapper extends smb {
360
 
 
361
 
        # variables
362
 
 
363
 
        private $stream, $url, $parsed_url = array (), $mode, $tmpfile;
364
 
        private $need_flush = FALSE;
365
 
        private $dir = array (), $dir_index = -1;
366
 
 
367
 
 
368
 
        # directories
369
 
 
370
 
        function dir_opendir ($url, $options) {
371
 
                if ($d = $this->getdircache ($url)) {
372
 
                        $this->dir = $d;
373
 
                        $this->dir_index = 0;
374
 
                        return TRUE;
375
 
                }
376
 
                $pu = smb::parse_url ($url);
377
 
                switch ($pu['type']) {
378
 
                        case 'host':
379
 
                                if ($o = smb::look ($pu)) {
380
 
                                        $this->dir = $o['disk'];
381
 
                                        $this->dir_index = 0;
382
 
                                } else {
383
 
                                        trigger_error ("dir_opendir(): list failed for host '{$pu['host']}'", E_USER_WARNING);
384
 
                                        return false;
385
 
                                }
386
 
                                break;
387
 
                        case 'share':
388
 
                        case 'path':
389
 
                                if (is_array($o = smb::execute ('dir "'.$pu['path'].'\*"', $pu))) {
390
 
                                        $this->dir = array_keys($o['info']);
391
 
                                        $this->dir_index = 0;
392
 
                                        $this->adddircache ($url, $this->dir);
393
 
                                        if(substr($url,-1,1)=='/'){
394
 
                                                $url=substr($url,0,-1);
395
 
                                        }
396
 
                                        foreach ($o['info'] as $name => $info) {
397
 
                                                smb::addstatcache($url . '/' . $name, $info);
398
 
                                        }
399
 
                                } else {
400
 
                                        trigger_error ("dir_opendir(): dir failed for path '".$pu['path']."'", E_USER_WARNING);
401
 
                                        return false;
402
 
                                }
403
 
                                break;
404
 
                        default:
405
 
                                trigger_error ('dir_opendir(): error in URL', E_USER_ERROR);
406
 
                                return false;
407
 
                }
408
 
                return TRUE;
409
 
        }
410
 
 
411
 
        function dir_readdir () {
412
 
                return ($this->dir_index < count($this->dir)) ? $this->dir[$this->dir_index++] : FALSE;
413
 
        }
414
 
 
415
 
        function dir_rewinddir () { $this->dir_index = 0; }
416
 
 
417
 
        function dir_closedir () { $this->dir = array(); $this->dir_index = -1; return TRUE; }
418
 
 
419
 
 
420
 
        # cache
421
 
 
422
 
        function adddircache ($url, $content) {
423
 
                $url = str_replace('//', '/', $url);
424
 
                $url = rtrim($url, '/');
425
 
                global $__smb_cache;
426
 
                return $__smb_cache['dir'][$url] = $content;
427
 
        }
428
 
 
429
 
        function getdircache ($url) {
430
 
                $url = str_replace('//', '/', $url);
431
 
                $url = rtrim($url, '/');
432
 
                global $__smb_cache;
433
 
                return isset ($__smb_cache['dir'][$url]) ? $__smb_cache['dir'][$url] : FALSE;
434
 
        }
435
 
 
436
 
        function cleardircache ($url='') {
437
 
                $url = str_replace('//', '/', $url);
438
 
                $url = rtrim($url, '/');
439
 
                global $__smb_cache;
440
 
                if ($url == ''){
441
 
                        $__smb_cache['dir'] = array ();
442
 
                }else{
443
 
                        unset ($__smb_cache['dir'][$url]);
444
 
                }
445
 
        }
446
 
 
447
 
 
448
 
        # streams
449
 
 
450
 
        function stream_open ($url, $mode, $options, $opened_path) {
451
 
                $this->url = $url;
452
 
                $this->mode = $mode;
453
 
                $this->parsed_url = $pu = smb::parse_url($url);
454
 
                if ($pu['type'] <> 'path') trigger_error('stream_open(): error in URL', E_USER_ERROR);
455
 
                switch ($mode) {
456
 
                        case 'r':
457
 
                        case 'r+':
458
 
                        case 'rb':
459
 
                        case 'a':
460
 
                        case 'a+':  $this->tmpfile = tempnam('/tmp', 'smb.down.');
461
 
                                $result = smb::execute ('get "'.$pu['path'].'" "'.$this->tmpfile.'"', $pu);
462
 
                                if($result === false){
463
 
                                        return $result;
464
 
                                }
465
 
                                break;
466
 
                        case 'w':
467
 
                        case 'w+':
468
 
                        case 'wb':
469
 
                        case 'x':
470
 
                        case 'x+':  $this->cleardircache();
471
 
                                $this->tmpfile = tempnam('/tmp', 'smb.up.');
472
 
                                $this->need_flush=true;
473
 
                }
474
 
                $this->stream = fopen ($this->tmpfile, $mode);
475
 
                return TRUE;
476
 
        }
477
 
 
478
 
        function stream_close () { return fclose($this->stream); }
479
 
 
480
 
        function stream_read ($count) { return fread($this->stream, $count); }
481
 
 
482
 
        function stream_write ($data) { $this->need_flush = TRUE; return fwrite($this->stream, $data); }
483
 
 
484
 
        function stream_eof () { return feof($this->stream); }
485
 
 
486
 
        function stream_tell () { return ftell($this->stream); }
487
 
 
488
 
        // PATCH: the wrapper must return true when fseek succeeded by returning 0.
489
 
        function stream_seek ($offset, $whence=null) { return fseek($this->stream, $offset, $whence) === 0; }
490
 
 
491
 
        function stream_flush () {
492
 
                if ($this->mode <> 'r' && $this->need_flush) {
493
 
                        smb::clearstatcache ($this->url);
494
 
                        smb::execute ('put "'.$this->tmpfile.'" "'.$this->parsed_url['path'].'"', $this->parsed_url);
495
 
                        $this->need_flush = FALSE;
496
 
                }
497
 
        }
498
 
 
499
 
        function stream_stat () { return smb::url_stat ($this->url); }
500
 
 
501
 
        function __destruct () {
502
 
                if ($this->tmpfile <> '') {
503
 
                        if ($this->need_flush) $this->stream_flush ();
504
 
                        unlink ($this->tmpfile);
505
 
 
506
 
                }
507
 
        }
508
 
 
509
 
}
510
 
 
511
 
###################################################################
512
 
# Register 'smb' protocol !
513
 
###################################################################
514
 
 
515
 
stream_wrapper_register('smb', 'smb_stream_wrapper')
516
 
        or die ('Failed to register protocol');