elFinder.pm

Дмитрий Ривлин, 25.05.2010 18:46

Download (12.5 kB)

 
1
package Libs::elFinder;
2
3
require 5.004;
4
use strict;
5
use vars qw/$VERSION $DIRECTORY_SEPARATOR/;
6
7
use Libs::Others;
8
use Libs::Web;   # Âñå ÷òî ñâÿçàíî ñ WEB çàïðîñû îòâåòû è òàê äàëåå
9
use Libs::ReadF;
10
use Libs::Image;
11
12
13
$VERSION = "0.1.0-dev"; # Âåðñèÿ äâèæêà è API
14
$DIRECTORY_SEPARATOR='/';
15
16
17
18
sub _hash{
19
my ($str)=@_;
20
#return Libs::Others::GenMD5($str);
21
return $str;
22
}
23
24
sub _unhash{
25
my ($str)=@_;
26
#return Libs::Others::GenMD5($str);
27
return $str;
28
}
29
30
31
32
sub new{ # Ñîçäàíèå íîâîãî êëàññà. Îòñþäà íà÷èíàåòñÿ êëàññ
33
 my ($class,%cfg)=@_; #Mod - ñïèñîê ìîäóëåé äëÿ çàãðóçêè
34
 my $self = bless {}, $class;
35
36
%{$self->{CONF}} = (
37
'root'         => '',           # path to root directory
38
'URL'          => '',           # root directory URL
39
'rootAlias'    => 'Home',       # display this instead of root directory name
40
'disabled'     => [],           # list of not allowed commands
41
'dotFiles'     => 'false',      # display dot files
42
'dirSize'      => 'true',       # count total directories sizes
43
'fileMode'     => 0666,         # new files mode
44
'dirMode'      => 0777,         # new folders mode
45
'mimeDetect'   => 'auto',       # files mimetypes detection method (finfo, mime_content_type, linux (file -ib), bsd (file -Ib), internal (by extensions))
46
'uploadAllow'  => [],           # mimetypes which allowed to upload
47
'uploadDeny'   => [],           # mimetypes which not allowed to upload
48
'uploadOrder'  => 'deny,allow', # order to proccess uploadAllow and uploadAllow options
49
'imgLib'       => 'auto',       # image manipulation library (imagick, mogrify, gd)
50
'tmbDir'       => '.tmb',       # directory name for image thumbnails. Set to "" to avoid thumbnails generation
51
'tmbCleanProb' => 1,            # how frequiently clean thumbnails dir (0 - never, 200 - every init request)
52
'tmbAtOnce'    => 5,            # number of thumbnails to generate per request
53
'tmbSize'      => 48,           # images thumbnails size (px)
54
'fileURL'      => 'true',       # display file URL in "get info"
55
'DateTimeFormat'=> '%d-%m-%Y %H:%i:%S', # file modification date format
56
'@Months'      => 'ßíâàðü,Ôåâðàëü,Ìàðò,Àïðåëü,Ìàé,Èþíü,Èþëü,Àâãóñò,Ñåíòÿáðü,Îêòÿáðü,Íîÿáðü,Äåêàáðü',
57
'@WeekDays'    => 'Âîñêðåñåíüå,Ïîíåäåëüíèê,Âòîðíèê,Ñðåäà,×åòâåð,Ïÿòíèöà,Ñóááîòà',
58
'logger'       => 'null',       # object logger
59
'aclObj'       => 'null',       # acl object (not implemented yet)
60
'aclRole'      => 'user',       # role for acl
61
'defaults'     => {             # default permisions
62
	'read'   => 'true',
63
	'write'  => 'true',
64
	'rm'     => 'true'
65
	},
66
'perms'        => [],           # individual folders/files permisions     
67
'debug'        => 'false',      # send debug to client
68
'archiveMimes' => [],           # allowed archive's mimetypes to create. Leave empty for all available types.
69
'archivers'    => [],            # info about archivers to use. See example below. Leave empty for auto detect
70
'WebCharset'   => 'WINDOWS-1251',
71
'UTF'	       => 'true'
72
);
73
$self->{CONF}       = { %{$self->{CONF}},%cfg };     # ×òåíèå ôàéëà êîíôèãóðàöèè
74
#                      { %{$self->{CONF}},Libs::ReadF::LoadCfgDB($self,'') }
75
 
76
 ($self->{FORM} , $self->{URL} ) = Libs::Web::ReadForms($self);      # ×òåíèå è ðàçáîð ñòðîêè URL,multipart,forms
77
 
78
 %{ $self->{CTYPE} }    = Libs::ReadF::LoadCfg($self,"$self->{CONF}->{'DirConf'}/mime.types",1);   # mime.types äëÿ ïðàâèëüíîãî âûâîäà ñàäåðæèìîãî
79
 %{$self->{RES}} = ();
80
81
82
83
 if (substr($self->{CONF}->{'root'}, -1) eq $DIRECTORY_SEPARATOR) {
84
     $self->{CONF}->{'root'} = substr($self->{CONF}->{'root'}, 0, -1); # Óáèðàåì ïîñëåäíèé /
85
   }
86
87
 %{$self->{CMD}} = (
88
'open'      => '_open',
89
'reload'    => '_reload',
90
'mkdir'     => '_mkdir',
91
'mkfile'    => '_mkfile',
92
'rename'    => '_rename',
93
'upload'    => '_upload',
94
'paste'     => '_paste',
95
'rm'        => '_rm',
96
'duplicate' => '_duplicate',
97
'read'      => '_fread',
98
'edit'      => '_edit',
99
'archive'   => '_archive',
100
'extract'   => '_extract',
101
'resize'    => '_resize',
102
'tmb'       => '_thumbnails',
103
'ping'      => '_ping'
104
);
105
106
#$ctr = Text::Iconv->new($self->{CONF}->{'WebCharset'},'UTF-8');
107
108
 return $self;
109
}
110
111
112
113
114
115
116
117
sub _run {
118
my ($self)=@_;
119
120
if ($self->{CONF}->{'root'} eq '' || is_dir($self->{CONF}->{'root'}) eq 'false') {$self->{RES}->{'error'} = 'Invalid backend configuration';return}
121
if (_isAllowed($self,$self->{CONF}->{'root'}, 'read') eq 'false') {$self->{RES}->{'error'} =  'Access denied';return}
122
123
my $cmd = '';
124
if ($self->{FORM}->{'cmd'} ne '') {$cmd = Libs::Others::SpaceTrim($self->{FORM}->{'cmd'});}
125
elsif ($self->{URL}->{'cmd'} ne '') {$cmd = Libs::Others::SpaceTrim($self->{URL}->{'cmd'});}
126
127
if (exists $self->{URL}->{'init'}) {
128
my $ts = $self->_utime();
129
$self->{RES}->{'disabled'} =  $self->{CONF}->{'disabled'};
130
%{$self->{RES}->{'params'}} = (
131
	'dotFiles'   => $self->{CONF}->{'dotFiles'},
132
	'uplMaxSize' => $self->{CONF}->{'uplMaxSize'},
133
	'archives'   => [],
134
	'extract'    => [],
135
	'url'        => $self->{CONF}->{'fileURL'} eq 'true' ? $self->{CONF}->{'URL'} : ''
136
	);
137
138
#if (isset($this->_commands['archive']) || isset($this->_commands['extract'])) {
139
#$this->_checkArchivers();
140
#if (isset($this->_commands['archive'])) {
141
#$this->_result['params']['archives'] = $this->_options['archiveMimes'];
142
#}
143
#if (isset($this->_commands['extract'])) {
144
#$this->_result['params']['extract'] = array_keys($this->_options['archivers']['extract']);
145
#}
146
#}
147
148
## clean thumbnails dir
149
if ($self->{CONF}->{'tmbDir'} ne '') {
150
   srand( time()* 1000000);
151
   if (rand(200) <= $self->{CONF}->{'tmbCleanProb'}) {
152
       my $ts2 = $self->_utime();
153
       opendir(DIR,$self->{CONF}->{'tmbDir'});
154
       my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);
155
       closedir(DIR);
156
       foreach my $subdir (@content){unlink($self->{CONF}->{'tmbDir'}.$DIRECTORY_SEPARATOR.$subdir)}
157
   }
158
}
159
}
160
161
162
if ($cmd ne '') {
163
 my $func=$self->{CMD}->{$cmd};
164
 $self->$func($self);
165
 } else {
166
$self->_open();
167
 }
168
}
169
170
171
172
173
174
175
176
177
sub _isAllowed{
178
my ($self,$path, $action)=@_;
179
#print "[$path, $action]\n";
180
#return 'true';
181
#print $self->{CONF}->{'defaults'}{$action};
182
#if    ($action eq 'read'){return 'true'}
183
#elsif ($action eq 'write'){return 'true'}
184
#elsif ($action eq 'rm'){return 'true'}
185
#return 'true';
186
#print "$self->{CONF}->{'root'}[$action]\n";
187
#$path = substr($path, length($self->{CONF}{'root'})+1);
188
189
#foreach ($self->{CONF}->{'perms'} as $regex => $rules) { # Äîâåñòè äî óìà
190
#  if (preg_match($regex, $path)) {
191
#      if (isset($rules[$action])) { return $rules[$action];}
192
#  }
193
#}
194
195
196
return (exists $self->{CONF}->{'defaults'}{$action}) ? $self->{CONF}->{'defaults'}{$action} : 'false';
197
}
198
199
200
201
sub _basename{
202
my ($path)=@_;
203
if (rindex($path,$DIRECTORY_SEPARATOR)==-1){return $path}
204
#my $str=$ctr->convert(substr($path,rindex($path,$DIRECTORY_SEPARATOR)+1));
205
206
return substr($path,rindex($path,$DIRECTORY_SEPARATOR)+1)
207
}
208
209
sub is_dir{
210
my ($path)=@_;
211
if (-d "$path"){return 'true'}
212
return 'false';
213
}
214
215
sub _isAccepted{
216
my ($self,$file)=@_;
217
$file=_basename($file);
218
if ('.' eq $file || '..' eq $file) {return 'false';}
219
if ($self->{CONF}->{'dotFiles'} ne 'true' && '.' eq substr($file, 0, 1)) {return 'false';}
220
return 'true';
221
}
222
223
224
sub _tree{
225
    my ($self,$path) = @_;
226
    my %dir = (
227
              'hash'  => _hash("$path"),
228
              'name'  =>  $path eq $self->{CONF}->{'root'} && $self->{CONF}->{'rootAlias'} ne '' ? $self->{CONF}->{'rootAlias'} : _basename($path),
229
              'read'  => _isAllowed($self,$path, 'read'),
230
              'write' => _isAllowed($self,$path, 'write'),
231
              'dirs'  => []
232
                 );
233
    if ($dir{'read'} eq 'true'){
234
     opendir(DIR,$path);
235
     my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);  
236
     closedir(DIR);
237
     foreach my $subdir (grep {-d "$path/$_" && _isAccepted($self,"$path/$_") eq 'true'} @content){
238
           my %dirs=_tree($self,"$path/$subdir");
239
           push @{$dir{'dirs'}},{%dirs};
240
     }
241
    }
242
   return %dir;
243
 }
244
245
sub _cwd{
246
my ($self,$path)=@_;
247
my $rel  = $self->{CONF}->{'rootAlias'} ne '' ? $self->{CONF}->{'rootAlias'} : _basename($self->{CONF}->{'root'});
248
my $name;
249
if ($path eq $self->{CONF}->{'root'}) {$name = $rel;}
250
else {
251
      $name = _basename($path);
252
      $rel .= $DIRECTORY_SEPARATOR.substr($path, length($self->{CONF}->{'root'})+1);
253
}
254
%{$self->{RES}->{'cwd'}} = (
255
'hash'       => _hash("$path"),
256
'name'       => $name,
257
'mime'       => 'directory',
258
'rel'        => $rel,
259
'size'       => 0,
260
'date'       => Libs::Others::LocalDate($self,$self->{CONF}->{'DateTimeFormat'},'',int(-M "$path")),
261
'read'       => 'true',
262
'write'      => _isAllowed($self,$path, 'write'),
263
'rm'         => $path eq $self->{CONF}->{'root'} ? 'false' : _isAllowed($self,$path, 'rm')
264
);
265
}
266
267
268
sub _cdc{
269
my ($self,$path)=@_;
270
opendir(DIR,$path); 
271
my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);
272
closedir(DIR);
273
foreach my $subdir ( grep {_isAccepted($self,"$path/$_") eq 'true'} sort {-f "$path/$a" cmp -f "$path/$b"} @content)
274
{push @{$self->{RES}->{'cdc'}},{_info($self,"$path/$subdir")};}
275
}
276
277
278
sub _info{
279
my ($self,$path)=@_;
280
my @info=(-l "$path") ? lstat("$path") : stat("$path");
281
my %info= (
282
 'hash'  => _hash("$path"),
283
 'mime'  => -d "$path" ? 'directory' : $self->_mimetype("$path"),
284
 'name'  => _basename("$path"), # Ñäåëàòü çàìåíó äâîéíûõ êàâû÷åê
285
 'date'  =>  Libs::Others::LocalDate($self,$self->{CONF}->{'DateTimeFormat'},'',$info[9]),
286
 'size'  => -d "$path" ?  0 : $info[7],
287
 'read'  => _isAllowed($self,"$path", 'read'),
288
 'write' => _isAllowed($self,"$path", 'write'),
289
 'rm'    => _isAllowed($self,"$path", 'rm'),
290
);
291
if ($info{'mime'} ne 'directory') {
292
 if ($self->{CONF}->{'fileURL'} eq 'true' && $info{'read'}) {
293
    #$info{'url'} = $this->_path2url($lpath ? $lpath : $path);
294
 }
295
296
if ($info{'mime'} =~ /image/) {
297
298
  if ('false' != (my @s = Libs::Image::GetImgInfo($self,$path))) { $info{'dim'} = $s[0].'x'.$s[1];}
299
  if ($info{'read'} eq 'true') {
300
      $info{'resize'} = ( exists $info{'dim'});
301
      #$tmb = _tmbPath($self,$path);
302
303
      #if (-f $tmb) {$info{'tmb'}  = _path2url($self,$tmb);}
304
      #elsif ($info{'resize'}) {$self->{RES}->{'tmb'} = 'true'}
305
   }
306
 }
307
}
308
return %info;
309
}
310
311
312
sub _mimetype{
313
my ($self,$path)=@_;
314
if (rindex($path,$DIRECTORY_SEPARATOR)!=-1){$path=substr($path,rindex($path,$DIRECTORY_SEPARATOR)+1)}
315
my ($name,$ext);
316
if (rindex($path,'.')!=-1){
317
 $ext=substr($path,rindex($path,'.')+1);
318
 $name=substr($path,0,rindex($path,'.'))
319
}
320
else {$name=$path}
321
my $mt=$self->{CTYPE}->{lc($ext)};
322
$mt=($mt ne '') ? $mt :'unknown;';
323
return $mt;
324
}
325
326
sub _content{
327
my ($self,$path,$flag)=@_;
328
_cwd($self,$path);
329
_cdc($self,$path);
330
if ($self->{RES}->{'cdc'} eq '') {push @{$self->{RES}->{'cdc'}},;}
331
if (exists $self->{URL}->{tree} || lc($flag) eq 'true') { $self->{RES}->{'tree'} = {_tree($self,$self->{CONF}->{'root'})};}
332
}
333
334
335
336
sub _open{
337
my ($self)=@_;
338
my $path = $self->{CONF}->{'root'};
339
340
if ($self->{URL}->{'target'} ne '' ){
341
my $p=_unhash($self->{URL}->{'target'});
342
  if (-r ($self->{URL}->{'target'})==0){
343
    if (! exists $self->{URL}->{'init'}) {$self->{RES}->{'error'} .= 'Invalid parameters';}
344
  } elsif (_isAllowed($self,$p, 'read') eq 'false') {
345
    if (! exists $self->{URL}->{'init'}) {$self->{RES}->{'error'} .= 'Access denied';}
346
  } else {$path = $p;}
347
}
348
349
if (exists $self->{URL}->{current}) {$self->{RES}->{'error'} .= "$self->{URL}->{current}<br>"}
350
351
_content($self,$path);
352
}
353
354
sub _rm{
355
my ($self)=@_;
356
if (($self->{URL}->{'current'} eq '')
357
|| (-r (Libs::Others::SpaceTrim(_unhash($self->{URL}->{'current'})))==0)
358
|| ($self->{URL}->{'targets[]'} eq '')) { # || !is_array($_GET['targets'])
359
return $self->{RES}->{'error'}.= 'Invalid parameters '. $self->{URL}->{'targets[]'};
360
}
361
362
foreach my $hash (split(',',$self->{URL}->{'targets[]'})) {
363
 $hash=_unhash($hash);
364
 if (-d $hash) {system("rm -r $hash")}
365
 else {unlink($hash);}
366
}
367
_content($self,_unhash($self->{URL}->{'current'}),'true');
368
}
369
370
371
sub _mkdir{
372
my ($self)=@_;
373
if (($self->{URL}->{'current'} eq '') || (-r (Libs::Others::SpaceTrim(_unhash($self->{URL}->{'current'})))==0)){
374
 return $self->{RES}->{'error'}.= 'Invalid parameters ';
375
 }
376
my $dir=$self->{URL}->{'current'};
377
my $name;
378
if (_isAllowed($self,$dir, 'write') eq 'false') {
379
   $self->{RES}->{'error'} = 'Access denied';
380
} elsif ('false' eq ($name = _checkName($self,$self->{URL}->{'name'})) ) {
381
   $self->{RES}->{'error'} = 'Invalid name';
382
} elsif (-r ($dir.$DIRECTORY_SEPARATOR.$name)) {
383
   $self->{RES}->{'error'} = 'File or folder with the same name already exists';
384
} elsif (! mkdir($dir.$DIRECTORY_SEPARATOR.$name, $self->{CONF}->{'dirMode'})) {
385
   $self->{RES}->{'error'} = 'Unable to create folder';
386
} else {
387
  $self->{RES}->{'select'} =(_hash($dir.$DIRECTORY_SEPARATOR.$name));
388
   _content($self,_unhash($self->{URL}->{'current'}),'true');
389
} 
390
}
391
392
393
sub _utime{
394
my ($self)=@_;
395
return time().'0';
396
}
397
398
sub _checkName{
399
my ($self,$n)=@_;
400
#$n = strip_tags(trim($n));
401
if ($self->{CONF}->{'dotFiles'} eq 'false' && '.' eq substr($n, 0, 1)) {
402
 return 'false';
403
}
404
return ($n =~ /[>|<|\/|:]+/) ? 'false' : $n;
405
}
406
407
408
1;