elFinder.pm

Troex Nevelin, 18.05.2010 13:45

Download (11.3 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
$VERSION = "0.1.0-dev"; # Версия движка и API
13
$DIRECTORY_SEPARATOR='/';
14
15
16
17
sub new{ # Создание нового класса. Отсюда начинается класс
18
 my ($class,%cfg)=@_; #Mod - список модулей для загрузки
19
 my $self = bless {}, $class;
20
21
%{$self->{CONF}} = (
22
'root'         => '',           # path to root directory
23
'URL'          => '',           # root directory URL
24
'rootAlias'    => 'Home',       # display this instead of root directory name
25
'disabled'     => [],           # list of not allowed commands
26
'dotFiles'     => 'false',      # display dot files
27
'dirSize'      => 'true',       # count total directories sizes
28
'fileMode'     => 0666,         # new files mode
29
'dirMode'      => 0777,         # new folders mode
30
'mimeDetect'   => 'auto',       # files mimetypes detection method (finfo, mime_content_type, linux (file -ib), bsd (file -Ib), internal (by extensions))
31
'uploadAllow'  => [],           # mimetypes which allowed to upload
32
'uploadDeny'   => [],           # mimetypes which not allowed to upload
33
'uploadOrder'  => 'deny,allow', # order to proccess uploadAllow and uploadAllow options
34
'imgLib'       => 'auto',       # image manipulation library (imagick, mogrify, gd)
35
'tmbDir'       => '.tmb',       # directory name for image thumbnails. Set to "" to avoid thumbnails generation
36
'tmbCleanProb' => 1,            # how frequiently clean thumbnails dir (0 - never, 200 - every init request)
37
'tmbAtOnce'    => 5,            # number of thumbnails to generate per request
38
'tmbSize'      => 48,           # images thumbnails size (px)
39
'fileURL'      => 'true',       # display file URL in "get info"
40
'DateTimeFormat'=> '%d-%m-%Y %H:%i:%S', # file modification date format
41
'@Months'      => 'Январь,Февраль,Март,Апрель,Май,Июнь,Июль,Август,Сентябрь,Октябрь,Ноябрь,Декабрь',
42
'@WeekDays'    => 'Воскресенье,Понедельник,Вторник,Среда,Четвер,Пятница,Суббота',
43
'logger'       => 'null',       # object logger
44
'aclObj'       => 'null',       # acl object (not implemented yet)
45
'aclRole'      => 'user',       # role for acl
46
'defaults'     => {             # default permisions
47
	'read'   => 'true',
48
	'write'  => 'true',
49
	'rm'     => 'true'
50
	},
51
'perms'        => [],           # individual folders/files permisions     
52
'debug'        => 'false',      # send debug to client
53
'archiveMimes' => [],           # allowed archive's mimetypes to create. Leave empty for all available types.
54
'archivers'    => []            # info about archivers to use. See example below. Leave empty for auto detect
55
);
56
$self->{CONF}       = { %{$self->{CONF}},%cfg };     # Чтение файла конфигурации
57
#                      { %{$self->{CONF}},Libs::ReadF::LoadCfgDB($self,'') }
58
 
59
 ($self->{FORM} , $self->{URL} ) = Libs::Web::ReadForms($self);      # Чтение и разбор строки URL,multipart,forms
60
 
61
 %{ $self->{CTYPE} }    = Libs::ReadF::LoadCfg($self,"$self->{CONF}->{'DirConf'}/mime.types",1);   # mime.types для правильного вывода садержимого
62
 %{$self->{RES}} = ();
63
64
65
66
 if (substr($self->{CONF}->{'root'}, -1) eq $DIRECTORY_SEPARATOR) {
67
     $self->{CONF}->{'root'} = substr($self->{CONF}->{'root'}, 0, -1); # Убираем последний /
68
   }
69
70
 %{$self->{CMD}} = (
71
		'open'      => '_open',
72
		'reload'    => '_reload',
73
		'mkdir'     => '_mkdir',
74
		'mkfile'    => '_mkfile',
75
		'rename'    => '_rename',
76
		'upload'    => '_upload',
77
		'paste'     => '_paste',
78
		'rm'        => '_rm',
79
		'duplicate' => '_duplicate',
80
		'read'      => '_fread',
81
		'edit'      => '_edit',
82
		'archive'   => '_archive',
83
		'extract'   => '_extract',
84
		'resize'    => '_resize',
85
		'tmb'       => '_thumbnails',
86
		'ping'      => '_ping'
87
		);
88
89
 return $self;
90
}
91
92
93
94
95
sub _run {
96
my ($self)=@_;
97
98
if ($self->{CONF}->{'root'} eq '' || is_dir($self->{CONF}->{'root'}) eq 'false') {$self->{RES}->{'error'} = 'Invalid backend configuration';return}
99
if (_isAllowed($self,$self->{CONF}->{'root'}, 'read') eq 'false') {$self->{RES}->{'error'} =  'Access denied';return}
100
101
my $cmd = '';
102
if ($self->{FORM}->{'cmd'} ne '') {$cmd = Libs::Others::SpaceTrim($self->{FORM}->{'cmd'});}
103
elsif ($self->{URL}->{'cmd'} ne '') {$cmd = Libs::Others::SpaceTrim($self->{URL}->{'cmd'});}
104
105
if (exists $self->{URL}->{'init'}) {
106
my $ts = $self->_utime();
107
$self->{RES}->{'disabled'} =  $self->{CONF}->{'disabled'};
108
%{$self->{RES}->{'params'}} = (
109
	'dotFiles'   => $self->{CONF}->{'dotFiles'},
110
	'uplMaxSize' => $self->{CONF}->{'uplMaxSize'},
111
	'archives'   => [],
112
	'extract'    => [],
113
	'url'        => $self->{CONF}->{'fileURL'} eq 'true' ? $self->{CONF}->{'URL'} : ''
114
	);
115
116
#if (isset($this->_commands['archive']) || isset($this->_commands['extract'])) {
117
#$this->_checkArchivers();
118
#if (isset($this->_commands['archive'])) {
119
#$this->_result['params']['archives'] = $this->_options['archiveMimes'];
120
#}
121
#if (isset($this->_commands['extract'])) {
122
#$this->_result['params']['extract'] = array_keys($this->_options['archivers']['extract']);
123
#}
124
#}
125
126
## clean thumbnails dir
127
if ($self->{CONF}->{'tmbDir'} ne '') {
128
   srand( time()* 1000000);
129
   if (rand(200) <= $self->{CONF}->{'tmbCleanProb'}) {
130
       my $ts2 = $self->_utime();
131
       opendir(DIR,$self->{CONF}->{'tmbDir'});
132
       my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);
133
       closedir(DIR);
134
       foreach my $subdir (@content){unlink($self->{CONF}->{'tmbDir'}.$DIRECTORY_SEPARATOR.$subdir)}
135
   }
136
}
137
}
138
139
140
if ($cmd ne '') {
141
 my $func=$self->{CMD}->{$cmd};
142
 $self->$func($self);
143
 #$self->{RES}->{'error'} .= ' '.'cmd:'.$cmd." $self->{CMD}->{$cmd} <br>Targ - $self->{URL}->{'target'}<br>Cur -  $self->{URL}->{'current'}";
144
 } else {
145
#$self->{RES}->{'error'} .= ' '.'1 cmd:'.$cmd;
146
$self->_open();
147
 }
148
}
149
150
151
152
153
154
155
156
157
sub _isAllowed{
158
my ($self,$path, $action)=@_;
159
#print "[$path, $action]\n";
160
#return 'true';
161
#print $self->{CONF}->{'defaults'}{$action};
162
#if    ($action eq 'read'){return 'true'}
163
#elsif ($action eq 'write'){return 'true'}
164
#elsif ($action eq 'rm'){return 'true'}
165
#return 'true';
166
#print "$self->{CONF}->{'root'}[$action]\n";
167
#$path = substr($path, length($self->{CONF}{'root'})+1);
168
169
#foreach ($self->{CONF}->{'perms'} as $regex => $rules) { # Довести до ума
170
#  if (preg_match($regex, $path)) {
171
#      if (isset($rules[$action])) { return $rules[$action];}
172
#  }
173
#}
174
175
176
return (exists $self->{CONF}->{'defaults'}{$action}) ? $self->{CONF}->{'defaults'}{$action} : 'false';
177
}
178
179
180
sub _basename{
181
my ($path)=@_;
182
if (rindex($path,$DIRECTORY_SEPARATOR)==-1){return $path}
183
return substr($path,rindex($path,$DIRECTORY_SEPARATOR)+1);
184
}
185
186
sub is_dir{
187
my ($path)=@_;
188
if (-d "$path"){return 'true'}
189
return 'false';
190
}
191
192
sub _isAccepted{
193
my ($self,$file)=@_;
194
$file=_basename($file);
195
if ('.' eq $file || '..' eq $file) {return 'false';}
196
if ($self->{CONF}->{'dotFiles'} ne 'true' && '.' eq substr($file, 0, 1)) {return 'false';}
197
return 'true';
198
}
199
200
201
sub _tree{
202
    my ($self,$path) = @_;
203
    my %dir = (
204
              'hash'  => Libs::Others::GenMD5("$path"),
205
              'name'  =>  $path eq $self->{CONF}->{'root'} && $self->{CONF}->{'rootAlias'} ne '' ? $self->{CONF}->{'rootAlias'} : _basename($path),
206
              'read'  => _isAllowed($self,$path, 'read'),
207
              'write' => _isAllowed($self,$path, 'write'),
208
              'dirs'  => []
209
                 );
210
    if ($dir{'read'} eq 'true'){
211
     opendir(DIR,$path);
212
     my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);  
213
     closedir(DIR);
214
     foreach my $subdir (grep {-d "$path/$_" && _isAccepted($self,"$path/$_") eq 'true'} @content){
215
           my %dirs=_tree($self,"$path/$subdir");
216
           push @{$dir{'dirs'}},{%dirs};
217
     }
218
    }
219
   return %dir;
220
 }
221
222
sub _cwd{
223
my ($self,$path)=@_;
224
my $rel  = $self->{CONF}->{'rootAlias'} ne '' ? $self->{CONF}->{'rootAlias'} : _basename($self->{CONF}->{'root'});
225
my $name;
226
if ($path eq $self->{CONF}->{'root'}) {$name = $rel;}
227
else {
228
      $name = _basename($path);
229
      $rel .= $DIRECTORY_SEPARATOR.substr($path, length($self->{CONF}->{'root'})+1);
230
}
231
%{$self->{RES}->{'cwd'}} = (
232
	'hash'       => Libs::Others::GenMD5("$path"),
233
	'name'       => $name,
234
	'mime'       => 'directory',
235
	'rel'        => $rel,
236
	'size'       => 0,
237
	'date'       => Libs::Others::LocalDate($self,$self->{CONF}->{'DateTimeFormat'},'',int(-M "$path")),
238
	'read'       => 'true',
239
	'write'      => _isAllowed($self,$path, 'write'),
240
	'rm'         => $path eq $self->{CONF}->{'root'} ? 'false' : _isAllowed($self,$path, 'rm')
241
	);
242
}
243
244
245
sub _cdc{
246
my ($self,$path)=@_;
247
opendir(DIR,$path); 
248
my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);
249
closedir(DIR);
250
251
foreach my $subdir ( grep {_isAccepted($self,"$path/$_") eq 'true'} sort {-f "$path/$a" cmp -f "$path/$b"} @content)
252
{push @{$self->{RES}->{'cdc'}},{_info($self,"$path/$subdir")};}
253
}
254
255
256
sub _info{
257
my ($self,$path)=@_;
258
my @info=(-l "$path") ? lstat("$path") : stat("$path");
259
my %info= (
260
 'hash'  => Libs::Others::GenMD5("$path"),
261
 'mime'  => -d "$path" ? 'directory' : $self->_mimetype("$path"),
262
 'name'  => _basename("$path"), # Сделать замену двойных кавычек
263
 'date'  =>  Libs::Others::LocalDate($self,$self->{CONF}->{'DateTimeFormat'},'',$info[9]),
264
 'size'  => -d "$path" ?  0 : $info[7],
265
 'read'  => _isAllowed($self,"$path", 'read'),
266
 'write' => _isAllowed($self,"$path", 'write'),
267
 'rm'    => _isAllowed($self,"$path", 'rm'),
268
);
269
if ($info{'mime'} ne 'directory') {
270
 if ($self->{CONF}->{'fileURL'} eq 'true' && $info{'read'}) {
271
    #$info{'url'} = $this->_path2url($lpath ? $lpath : $path);
272
 }
273
274
if ($info{'mime'} =~ /image/) {
275
276
  if ('false' != (my @s = Libs::Image::GetImgInfo($self,$path))) { $info{'dim'} = $s[0].'x'.$s[1];}
277
  if ($info{'read'} eq 'true') {
278
      $info{'resize'} = ( exists $info{'dim'});
279
      #$tmb = _tmbPath($self,$path);
280
281
      #if (-f $tmb) {$info{'tmb'}  = _path2url($self,$tmb);}
282
      #elsif ($info{'resize'}) {$self->{RES}->{'tmb'} = 'true'}
283
   }
284
 }
285
}
286
return %info;
287
}
288
289
290
sub _mimetype{
291
my ($self,$path)=@_;
292
if (rindex($path,$DIRECTORY_SEPARATOR)!=-1){$path=substr($path,rindex($path,$DIRECTORY_SEPARATOR)+1)}
293
my ($name,$ext);
294
if (rindex($path,'.')!=-1){
295
 $ext=substr($path,rindex($path,'.')+1);
296
 $name=substr($path,0,rindex($path,'.'))
297
}
298
else {$name=$path}
299
my $mt=$self->{CTYPE}->{lc($ext)};
300
$mt=($mt ne '') ? $mt :'unknown;';
301
return $mt;
302
}
303
304
sub _content{
305
my ($self,$path)=@_;
306
_cwd($self,$path);
307
_cdc($self,$path);
308
if (exists $self->{URL}->{tree}) { $self->{RES}->{'tree'} = {_tree($self,$self->{CONF}->{'root'})};}
309
}
310
311
312
313
sub _open{
314
my ($self)=@_;
315
my $path = $self->{CONF}->{'root'};
316
my $p;
317
318
if (exists $self->{URL}->{'target'}) {
319
 $p=_findDir($self,Libs::Others::SpaceTrim($self->{URL}->{'target'}));
320
  if ('false' eq $p) {
321
    if (! exists $self->{URL}->{'init'}) {$self->{RES}->{'error'} .= 'Invalid parameters'. $p;}
322
  } elsif (_isAllowed($self,$p, 'read') eq 'false') {
323
    if (! exists $self->{URL}->{'init'}) {$self->{RES}->{'error'} .= 'Access denied';}
324
  } else {$path = $p;}
325
}
326
327
if (exists $self->{URL}->{current}) {$self->{RES}->{'error'} .= "$self->{URL}->{current}<br>"}
328
329
_content($self,$path);
330
}
331
332
333
334
sub _utime{
335
my ($self)=@_;
336
return time().'0';
337
}
338
339
340
sub _findDir{
341
my ($self,$hash, $path)=@_;
342
my $p='false';
343
if ($path eq '') {
344
 $path = $self->{CONF}->{'root'};
345
 if (Libs::Others::GenMD5("$path") eq $hash) {return $path;}
346
}
347
opendir(DIR,$path);
348
my @content = grep {!/^\.{1,2}$/} sort readdir(DIR);  
349
closedir(DIR);
350
foreach my $subdir (grep {-d "$path/$_" } @content){
351
  $p = $path.'/'.$subdir;
352
  if (Libs::Others::GenMD5("$p") eq $hash || ($p=_findDir($self,$hash,"$p")) ne 'false'){ last }
353
 }
354
return $p;
355
}
356
357
358
359
1;