Remove some warnings on user edition
[squasher.git] / webroot / squasher.class.php
1 <?php
2 require_once("../config.php");
3
4 function zfill($n, $a) {
5         return str_repeat("0", max(0,$a-strlen($n))) . $n;
6 }
7
8 function named_records_sort($named_recs, $order_by, $reverse=false, $flags=0) {
9         $named_hash = array();
10         foreach ($named_recs as $key => $fields)
11                 $named_hash[$key] = $fields[$order_by];
12
13         if ($reverse)
14                 arsort($named_hash,$flags=0) ;
15         else
16                 asort($named_hash, $flags=0);
17
18         $sorted_records = array();
19         foreach($named_hash as $key => $val)$sorted_records[$key] = $named_recs[$key];
20
21         return $sorted_records;
22 }
23
24 function validate_user($username, $password, $salt) {
25 global $db;
26         $creds['validated'] = false;
27         $query="SELECT * FROM users WHERE user_name = '".$db->real_escape_string($username)."'";
28         $q_result = $db->query($query);
29         while ($fetched_object = mysqli_fetch_object($q_result)) {
30                 if (md5($fetched_object->user_pass.$salt) == $password) {
31                         //validated
32                         $creds['user_id'] = $fetched_object->user_id;
33                         $creds['user_name'] = $fetched_object->user_name;
34                         $creds['user_level'] = $fetched_object->user_level;
35                         $creds['validated'] = true;
36                         $_SESSION['creds'] = $creds;
37                         log_event('login', null);
38                 }
39         }
40         $_SESSION['creds'] = $creds;
41         return $creds['validated'];
42 }
43
44
45 function get_smarty() {
46         require_once(SQUASHER_SMARTY_SOURCE); // See config.php
47
48         $smarty = new Smarty;
49         $smarty->setTemplateDir(SQUASHER_SMARTY_TEMPLATES)
50                ->setCompileDir(SQUASHER_SMARTY_TEMPLATES_C)
51                ->setCacheDir(SQUASHER_SMARTY_CACHE);
52
53         return $smarty;
54 }
55
56
57 function log_event($action, $filename, $hash=null, $debugmsg=null) {
58 global $db;
59         if ($hash===null)
60                 $hash = str_repeat("0",32);
61                 
62         if ($debugmsg!==null) {
63                 $user_id = -1;
64                 $user_name = 'squasher-web';
65                 $ip = $debugmsg;
66         } else {
67                 $user_id = $_SESSION['creds']['user_id'];
68                 $user_name = $_SESSION['creds']['user_name'];
69                 $ip = $_SERVER['REMOTE_ADDR'];
70         }
71
72         $hash = $hash===null ? 'NULL' : "'".$db->real_escape_string($hash)."'";
73         $filename = "'".$db->real_escape_string($filename)."'";
74         $action = "'".$db->real_escape_string($action)."'";
75         $user_name = "'". $db->real_escape_string($user_name)."'";
76         $ip = "'". $db->real_escape_string($ip)."'";
77
78         @$db->query("INSERT INTO log (hash,file,action,user_id,user_name,ip,date) VALUES ($hash, $filename, $action, $user_id, $user_name, $ip, NOW())");
79 }
80
81
82 class squashweb {
83
84 var $configs = array();
85 var $files = array();
86 var $subfolders = array();
87 var $folderrights;
88 var $userrights;
89 var $history = array();
90
91 function get_configs() {
92         return $this->configs;
93 }
94
95 function subfolders() {
96         return $this->subfolders;
97 }
98
99 function get_config($h) {
100
101         return $this->configs[$h];
102 }
103
104 function folderrights() {
105         return $this->folderrights;
106 }
107
108 function userrights() {
109         return $this->userrights;
110 }
111
112 function update_history() {
113         $q="SELECT md5_hash,file,completed,checked FROM file_hash";
114         $r=$this->db->query($q);
115         while($o=mysqli_fetch_object($r)) {
116                 $this->history[$o->md5_hash]['file']=$o->file;
117                 $this->history[$o->md5_hash]['completed']=$o->completed;
118                 $this->history[$o->md5_hash]['checked']=$o->checked;
119         }
120 }
121
122 function get_users($user_level) {
123         $q = "SELECT * FROM users";
124         if ($user_level<200) // super user have no restrictions at all
125                 $q .= " WHERE user_level < ".$user_level;
126         $q .= " ORDER BY user_name ASC";
127         $r = $this->db->query($q);
128
129         $return = array();
130         while ($o = mysqli_fetch_object($r)) {
131                 $return[$o->user_id]['id']              = $o->user_id;
132                 $return[$o->user_id]['name']    = $o->user_name;
133                 $return[$o->user_id]['level']   = $o->user_level;
134                 $return[$o->user_id]['enabled'] = ($o->user_pass == '') ? false : true ;
135         }
136
137         return $return;
138 }
139
140 function get_logs($type='all') {
141         $db=$this->db;
142         $q="SELECT log.* FROM log WHERE log.user_id != '1' and ip != '87.233.211.2' ";
143         if ($_SESSION['creds']['user_id'] == 1)
144                 $q="SELECT log.* FROM log WHERE log.user_id != 'x' ";
145
146         if ($type != 'all')
147                 $q.= " AND log.action = '".$db->real_escape_string($type)."'";
148
149         $today     =" AND date > date(date_add(now(), interval -0 day)) ";
150         $yesterday =" AND date < date(date_add(now(), interval -0 day)) AND date > date(date_add(now(), interval -1 day)) ";
151         $lastweek  =" AND date < date(date_add(now(), interval -1 day)) AND date > date(date_add(now(), interval -6 day)) ";
152         $older     =" AND date < date(date_add(now(), interval -7 day)) AND date > date(date_add(now(), interval -30 day)) ";
153
154         $order=" ORDER BY log.log_id desc ";
155         $r = $db->query($q.$today.$order);
156         $return = array(
157                 'today'=>array(),
158                 'yesterday'=>array(),
159                 'lastweek'=>array(),
160                 'older'=>array(),
161                 );
162         while($a = mysqli_fetch_array($r)) {
163                 $qu="SELECT users.user_name FROM users LEFT JOIN log ON users.user_id = log.user_id WHERE log.ip='".$db->real_escape_string($a['ip'])."' GROUP BY users.user_name";
164                 $ru = $db->query($qu);
165                 $a['users_from_ip'] = " | ";
166                 while($au = mysqli_fetch_array($ru))
167                         $a['users_from_ip'] .= $au['user_name']." | ";
168                 $return['today'][$a['log_id']] = $a;
169         }
170         $r = $db->query($q.$yesterday.$order);
171         while($a = mysqli_fetch_array($r)) {
172                 $qu="SELECT users.user_name FROM users LEFT JOIN log ON users.user_id = log.user_id WHERE log.ip='".$db->real_escape_string($a['ip'])."' GROUP BY users.user_name";
173                 $ru = $db->query($qu);
174                 $a['users_from_ip'] = " | ";
175                 while($au = mysqli_fetch_array($ru))
176                         $a['users_from_ip'] .= $au['user_name']." | ";
177                 $return['yesterday'][$a['log_id']] = $a;
178         }
179         $r = $db->query($q.$lastweek.$order);
180         while($a = mysqli_fetch_array($r)) {
181                 $qu="SELECT users.user_name FROM users LEFT JOIN log ON users.user_id = log.user_id WHERE log.ip='".$db->real_escape_string($a['ip'])."' GROUP BY users.user_name";
182                 $ru = $db->query($qu);
183                 $a['users_from_ip'] = " | ";
184                 while($au = mysqli_fetch_array($ru))
185                         $a['users_from_ip'] .= $au['user_name']." | ";
186                 $return['lastweek'][$a['log_id']] = $a;
187         }
188         $r = $db->query($q.$older.$order);
189         while($a = mysqli_fetch_array($r)) {
190                 $qu="SELECT users.user_name FROM users LEFT JOIN log ON users.user_id = log.user_id WHERE log.ip='".$db->real_escape_string($a['ip'])."' GROUP BY users.user_name";
191                 $ru = $db->query($qu);
192                 $a['users_from_ip'] = " | ";
193                 while($au = mysqli_fetch_array($ru))
194                         $a['users_from_ip'] .= $au['user_name']." | ";
195                 $return['older'][$a['log_id']] = $a;
196         }
197
198         return $return;
199 }
200
201 function insert_users($u, $admin_level) {
202         $db=$this->db;
203         $user_name = $u['user_name'];
204         $user_pass = $u['user_pass'];
205         $user_level = (int)$u['user_level'];
206
207         $q = "INSERT INTO users (user_name,user_pass,user_level) VALUES ('".$db->real_escape_string($user_name)."', '".$db->real_escape_string(md5($user_pass))."', ".$user_level.")";
208         $r = $db->query($q);
209 }
210
211 /*
212  * if user_level is 0, it means we don't really touch it, but we clear the password (can't log in anymore)
213  */
214 function update_users($u, $user_id) {
215         $db=$this->db;
216         $user_id = (int)$user_id;
217         $user_name = @$u['user_name'];
218         $user_pass = @$u['user_pass'];
219         if (array_key_exists('user_level', $u))
220                 $user_level = $u['user_level'];
221         else
222                 $user_level = null;
223         if ($user_name) {
224                 $q = "UPDATE users SET user_name = '".$db->real_escape_string($user_name)."' WHERE user_id = ".$user_id;
225                 $r = $db->query($q);
226         }
227         if ($user_pass) {
228                 $q = "UPDATE users SET user_pass = '".$db->real_escape_string(md5($user_pass))."' WHERE user_id = ".$user_id;
229                 $r = $db->query($q);
230         }
231         if ($user_level !== null) {
232                 if ($user_level > 0) {
233                         $q = "UPDATE users SET user_level = ".$user_level." WHERE user_id = ".$user_id;
234                         $r = $db->query($q);
235                 } else {
236                         $q = "UPDATE users SET user_pass = '' WHERE user_id = ".$user_id;
237                         $r = $db->query($q);
238                 }
239         }
240 }
241
242 function remove_users($user_id) {
243         $user_id = (int)$user_id;
244         $q = "DELETE FROM users WHERE user_id = ".$user_id;
245         $r = $this->db->query($q);
246 }
247
248
249 /**
250  * Get the permissions of a user over the file tree
251  *
252  * This builds a permission array, which is kind of recursive:
253  * The array keys are the name of the directories, and the values are an array
254  * hereby described.
255  * The special key __access__ indicates the permission of a given directory,
256  * its values can be:
257  * 0 --deny-all
258  * 1 --allow-dir-only
259  * 2 --allow-inc-subs
260  *
261  * Exemple:
262  *  [myas] => Array
263  *      [__access__] => 0
264  *  [myez] => Array
265  *      [__access__] => 1
266  *      [subfolder01] => Array
267  *          [__access__] => 2
268  *      [subfolder02] => Array
269  *          [__access__] => 2
270  *
271  * @param string user_id User id
272  * @return array Multidimensional array with dir and __access__ keys, and 0/1/2 values
273  */
274 function get_rights($user_id) {
275         $db=$this->db;
276         $result = array();
277
278         $q = "SELECT folder_path, access FROM user_rights WHERE user_id = ".(int)$user_id;
279         $r = $db->query($q);
280         while ($o = mysqli_fetch_object($r)) {
281
282                 //clean vars
283                 $arr_string = '$result';
284
285                 //get foldernames from path
286                 if ($o->folder_path != '/') {
287                         $path = $o->folder_path;
288                         if ($path{0}=='/')
289                                 $path=substr($path,1);
290                         $folder_arr = explode('/',$path);
291
292                         //create folder structure array
293                         foreach ($folder_arr AS $key => $value) {
294                                 $value_escaped = str_replace("'", "\\'", $value);
295                                 $arr_string .= "['".$value_escaped."']";
296                         }
297                 }
298                 $arr_string .= "['__access__']";
299
300                 eval($arr_string." = '".$o->access."';");
301         }
302         return $result;
303 }
304
305
306 /**
307  * Get super user permissions, full recursive access on /
308  *
309  * @return array Permissions
310  */
311 function get_superuser_rights() {
312         return  array('__access__' => 2);
313 }
314
315
316 /**
317  * Initialise this->folderrights or this->$userrights
318  *
319  * this->folderrights are the permissions of the logged in user
320  * this->userrights are the permissions of the user beeing edited
321  * 
322  * @see get_rights
323  *
324  * @param string user_id User id or -1 for full access
325  * @param string type 'folderrights' or 'userrights'
326  * 
327  */
328 function give_rights($user_id, $type='folderrights') {
329         if ($user_id == -1)
330                 $rights = $this->get_superuser_rights();
331         else
332                 $rights = $this->get_rights($user_id);
333
334         if ($type=='folderrights')
335                 $this->folderrights = $rights;
336         else // $type=='userrights'
337                 $this->userrights = $rights;
338 }
339
340 function update_rights($edited_user, $m, $admin_level) {
341         $db=$this->db;
342         $q = "SELECT count(*) result FROM users WHERE user_id = ".(int)$edited_user." AND user_level < ".(int)$admin_level;
343         $r = $db->query($q);
344         $o = mysqli_fetch_object($r);
345
346         if ($o->result) {
347                 foreach ($m AS $path => $access) {
348                         $p_q = "SELECT count(*) result FROM user_rights WHERE user_id = ".(int)$edited_user." AND folder_path = '".$db->real_escape_string($path)."'";
349                         $p_r = $db->query($p_q);
350                         $p_o = mysqli_fetch_object($p_r);
351                         if ($p_o->result == 1)
352                                 $db->query("UPDATE user_rights SET access = ".(int)$access." WHERE folder_path = '".$db->real_escape_string($path)."' AND user_id = ".(int)$edited_user);
353                         if ($p_o->result == 0)
354                                 $db->query("INSERT INTO user_rights (user_id,folder_path,access) values (".(int)$edited_user.",'".$db->real_escape_string($path)."',".(int)$access.") ");
355                 }
356         }
357 }
358
359
360 function show_rights_tree($path, $depth=0, $userid=0) {
361
362         if ($userid==0)
363                 return false;
364         if ($depth==0)
365                 $this->give_rights($userid, 'userrights');
366
367         // access = 0 --deny-all
368         // access = 1 --allow-dir-only
369         // access = 2 --allow-inc-subs
370
371         $layout = '';
372         $style = '';
373
374         for ($i=0; $i<$depth; $i++)
375                 $layout .= " ";
376         if ($dir = opendir(SQUASHER_UPLOADS_DIR.$path)) {
377                 $layout .= "<div style='clear:both;' >\n";
378                 $f = 0;
379                 while (false !== ($file = readdir($dir))) {
380                         $files_array[] = $file;
381                 }
382                 asort($files_array);
383                 foreach ($files_array as $f_index => $file) {
384                         if (($file{0} !== ".") && ($file !== ".."))
385                         {
386                                 $filename = $path=='/' ? $path.$file : $path.'/'.$file;
387                                 if (!is_file(SQUASHER_UPLOADS_DIR.$filename) && $this->got_rights_array($filename) > 0) {
388                                         $f++;
389                                         $name = $filename;
390                                         $check = $this->got_rights_array_admin($filename, $this->userrights);
391                                         $check_all = '';
392                                         $check_allow = '';
393                                         $check_deny = '';
394                                         switch($check) {
395                                                 case 2:
396                                                         $check_all = 'checked';
397                                                         break;
398                                                 case 1:
399                                                         $check_allow = 'checked';
400                                                         break;
401                                                 case 0:
402                                                 default:
403                                                         $check_deny = 'checked';
404                                                         break;
405                                         }
406
407                                         if ($f==1)
408                                                 $style[$depth] = ".depth".$depth."{float:right;width:".(600-($depth*10))."px;border-left:2px solid #FFFFFF;border-top:1px solid #FFFFFF;background:#".dechex(14-$depth).dechex(14-$depth).dechex(14-$depth).dechex(14-$depth).dechex(14-$depth).dechex(14-$depth).";}";
409                                         if ($f==1)
410                                                 $layout .= "<div class='depth".$depth."'>";
411                                         $layout .= "<div class='white_border' >".htmlspecialchars($file)."</div>\n";
412                                         $name_escaped = htmlspecialchars($name);
413                                         $layout .= '<div class="check_deny"><input name="m['.$name_escaped.']" value=0 type=radio '.$check_deny."></div>\n";
414                                         $layout .= '<div class="check_allow"><input name="m['.$name_escaped.']" value=1 type=radio '.$check_allow."></div>\n";
415                                         $layout .= '<div class="check_all"><input name="m['.$name_escaped.']" value=2 type=radio '.$check_all."></div>\n";
416                                         $sub_return = $this->show_rights_tree($filename,$depth+1,$userid);
417                                         if (is_array($style) && is_array($sub_return['style']))
418                                                 $style = $style + $sub_return['style'];
419                                         $layout .= $sub_return['layout'];
420                                 }
421                         }
422                 }
423                 if ($f!=0)
424                         $layout .= "</div>";
425                 $layout .= "</div>\n";
426         }
427
428         $return['style'] = $style;
429         $return['layout'] = $layout;
430
431         return $return;
432 }
433
434 function got_rights_array($needle, $haystack='', $c=0) {
435         // used by:
436         // - read_single_file
437         // - read_directory
438         // - show_rights_tree
439
440         if (!is_array($haystack))
441                 $haystack = $this->folderrights;
442
443         // check root rights
444         if ($needle{0} == '/' && @$haystack['__access__'] == 2 )
445                 return 2;
446
447         // remove leading /
448         if ($needle{0}=='/')
449                 $needle = substr($needle, 1);
450
451         $needle_arr = explode('/', $needle);
452         $n = count($needle_arr);
453         $d = $c + 1;
454
455         foreach ($haystack as $k => $v) {
456                 if ($needle_arr[$c] == $k) {
457                         if (!is_array(@$v['__access__'])) {
458                                 if ($v['__access__'] == 2             ) return 2;
459                                 if ($v['__access__'] == 1 && $d == $n ) return 1;
460                                 if ($v['__access__'] == 0 && $d == $n ) return 0;
461                         } else {
462                                 $return = $this->got_rights_array($needle, $v, $d);
463                         }
464                 }
465         }
466         return $return;
467 }
468
469 function got_rights_array_admin($needle, $haystack='', $c=0) {
470         // used by:
471         // - show_rights_tree
472
473         if (!is_array($haystack))
474                 $haystack = $this->folderrights;
475
476         // check root rights
477         if ($needle{0} == '/' && @$haystack['__access__'] == 2 )
478                 return 2;
479
480         // remove leading /
481         if ($needle{0} == '/')
482                 $needle = substr($needle, 1);
483
484         $needle_arr = explode('/', $needle);
485         $n = count($needle_arr);
486         $d = $c + 1;
487         $return = 0;
488
489         if ($c < $n) {
490                 if (@$haystack['__access__'] == 2)
491                         return $haystack['__access__'];
492                 if (is_array($haystack[$needle_arr[$c]]))
493                         $return = $this->got_rights_array_admin($needle, $haystack[$needle_arr[$c]], $d);
494         } else {
495                 if (@$haystack['__access__'] > 0)
496                         $return = $haystack['__access__'];
497         }
498
499         return $return;
500 }
501
502 function got_rights_array_recursive($needle, $haystack='', $c=0) {
503         // used by:
504         // - read_directory, for subfolders
505
506         if (!is_array($haystack))
507                 $haystack = $this->folderrights;
508
509         // check root rights
510         if($needle{0}=='/' && @$haystack['__access__'] == 2 )
511                 return 2;
512
513         // check folder rights
514         if($needle{0}=='/')
515                 $needle=substr($needle,1);
516
517         $needle_arr = explode('/', $needle);
518         $n = count($needle_arr);
519         $d = $c + 1;
520         $return = 0;
521
522         foreach($haystack as $k => $v) {
523                 if ($c < sizeof($needle_arr) && $needle_arr[$c] == $k) {
524                         if ($c < $n) {
525                                 if ($v['__access__'] == 2)
526                                         $return = $return + $v['__access__'];
527                                 $return = $return + $this->got_rights_array_recursive($needle, $v, $d);
528                         } else {
529                                 $return = $return + $this->in_array_recursive($v);
530                         }
531                 } elseif ($c == $n) {
532                         $return = $return + $v['__access__'];
533                         if($k != '__access__')$return = $return + $this->in_array_recursive($v);
534                 }
535         }
536
537         return $return;
538 }
539
540 function in_array_recursive($haystack) {
541         $return = 0;
542         if (is_array($haystack)) {
543                 foreach ($haystack as $key1 => $value1) {
544                         if (is_array($value1)) {
545                                 $return = $return + $this->in_array_recursive($value1);
546                         }
547                         elseif ($value1 > 0) {
548                                 return $value1;
549                         }
550                 }
551         }
552         return $return;
553 }
554
555 function read_single_file($path, $file) {
556         $filename = $path=='/' ? $path.$file : $path.'/'.$file;
557         $fsfilename = SQUASHER_UPLOADS_DIR.$filename; // name on the file system
558         $i = 0;
559         if ($this->got_rights_array($path) > 0) {
560                 if (is_file($fsfilename.'.Completed'))
561                         $ext='.Completed';
562                 if (is_file($fsfilename.'.InProgress'))
563                         $ext='.InProgress';
564                 if (is_file($fsfilename.'.Starting'))
565                         $ext='.Starting';
566                 if (is_file($fsfilename.'.Processed'))
567                         $ext='.Processed';
568                 $fsfilename .= $ext;
569                 $handle = @fopen($fsfilename, "rb");
570                 $sub_pos = strpos($file, $ext);
571                 $base_name = substr($file, 0, $sub_pos);
572                 $filecontent = @fread($handle, @filesize($fsfilename));
573                 $config[$i] = explode("\r\n", $filecontent);
574                 /***
575                 *       $config:: array
576                 *       [0]     ->      versioncode
577                 *       [1]     ->      date&time
578                 *       [2]     ->      filename
579                 *       [3]     ->      filesize
580                 *       [4]     ->      chunksize
581                 *       [5]     ->      chunkcount
582                 *       [6]     ->      CRC32 checksum
583                 ***/
584                 if (@filesize($fsfilename) > 0) {
585                         $h = md5($path."/".$config[$i][2]);
586                         $this->configs[$h] = $config[$i];
587                         $this->configs[$h]['squashed'] = true;
588                         $this->configs[$h]['path'] = $path;
589                         $this->configs[$h]['status'] = substr($ext, 1);
590                         $this->configs[$h]['mime'] = $this->set_mime($this->configs[$h][2]);
591                         $this->configs[$h]['hidden'] = is_file(SQUASHER_UPLOADS_DIR.$path.'/'.$base_name.'.hidden');
592                         //to prevent dates of 1-1-1970 we set te dates of the config file
593                         $this->configs[$h]['added'] = filectime($fsfilename);
594                         $this->configs[$h]['lastchange'] = filemtime($fsfilename);
595                         fclose($handle);
596                         $this->populate_stats($path, $h);
597                         //insert hash in db
598                         #$this->update_hash($h,$path."/".$config[$i][2]);
599                         //check stats
600                         $this->check_stats($h);
601                 }
602         }
603 }
604
605
606 function read_directory($path, $getsubs=false, $getfirstfiles=true, $getdeepfiles=true, $populate=true) {
607         $fsdir = $path=='/' ? SQUASHER_UPLOADS_DIR : SQUASHER_UPLOADS_DIR.$path;
608         $hdir = @opendir(SQUASHER_UPLOADS_DIR.$path);
609         if (!$hdir)
610                 return;
611         $i = 0;
612         while (false !== ($file = readdir($hdir))) {
613                 if ($file{0} == "." || substr($file,0,2) == "SQ")
614                         continue;       // skip this file
615                 $filename = $path=='/' ? $path.$file : $path.'/'.$file;
616                 $fsfilename = SQUASHER_UPLOADS_DIR.$filename; // name on the file system
617                 if (!is_file($fsfilename) && strpos($filename, '/recieving/')!==0) {
618                         if ($getsubs) {
619                                 if ($this->got_rights_array_recursive($filename) > 0) {
620                                         $key = $path;
621                                         if ($key != '/')
622                                                 $key .=  '/';
623                                         $key .= $file;
624                                         $this->subfolders[$key] = $file;
625                                 }
626                         }
627                         if ($getdeepfiles)
628                                 $this->read_directory($filename, false, $getdeepfiles, $getdeepfiles, $populate);
629                 } elseif (strpos($filename,'/ftp/')===0) {
630                         //ftp files
631                         if ($this->got_rights_array($path) > 0 && !strpos($filename, '.hidden') ) {
632                                 $h = md5($filename);
633                                 $name_only = substr($filename, strlen($path)+1); // this is $file
634                                 $file_structure = explode('.', $name_only); // array of dot separated name fragment
635                                 $ext = array_pop($file_structure); // extension
636                                 $base_name = array_pop($file_structure); // (erk)
637                                 $this->configs[$h]['path'] = $path;
638                                 $this->configs[$h][0] = 'manual ftp';
639                                 $this->configs[$h][2] = $name_only;
640                                 $this->configs[$h][3] = filesize($fsfilename);
641                                 $this->configs[$h]['added'] = filectime($fsfilename);
642                                 $this->configs[$h]['lastchange'] = filemtime($fsfilename);
643                                 $this->configs[$h]['status'] = 'unknown';
644                                 $this->configs[$h]['squashed'] = false;
645                                 $this->configs[$h]['mime'] = $this->set_mime($name_only);
646                                 $this->configs[$h]['hidden'] = is_file(SQUASHER_UPLOADS_DIR.$path.'/'.$base_name.'.hidden');
647                         }
648                 } elseif ($getfirstfiles) {
649                         //squashed files
650                         if ($this->got_rights_array($path) > 0) {
651                                 if (strpos($filename, '.Completed') || strpos($filename, '.InProgress') || strpos($filename, '.Starting') || strpos($filename, '.Processed')) {
652                                         $i++;
653                                         $handle = @fopen($fsfilename, "rb");
654                                         if (strpos($file,'.Completed'))
655                                                 $ext='.Completed';
656                                         if (strpos($file,'.InProgress'))
657                                                 $ext='.InProgress';
658                                         if (strpos($file,'.Starting'))
659                                                 $ext='.Starting';
660                                         if (strpos($file,'.Processed'))
661                                                 $ext='.Processed';
662                                         $sub_pos = strpos($file, $ext);
663                                         $base_name = substr($file, 0, $sub_pos);
664                                         $filecontent = @fread($handle, @filesize($fsfilename));
665                                         $config[$i] = explode("\r\n", $filecontent);
666
667                                         /***
668                                         *       $config:: array
669                                         *       [0]     ->      versioncode
670                                         *       [1]     ->      date&time
671                                         *       [2]     ->      filename
672                                         *       [3]     ->      filesize
673                                         *       [4]     ->      chunksize
674                                         *       [5]     ->      chunkcount
675                                         *       [6]     ->      CRC32 checksum
676                                         ***/
677
678                                         if (@filesize($fsfilename) > 0) {
679                                                 $h = md5($path."/".$config[$i][2]);
680                                                 $this->configs[$h] = $config[$i];
681                                                 $this->configs[$h]['squashed'] = true;
682                                                 $this->configs[$h]['path'] = $path;
683                                                 $this->configs[$h]['status'] = substr($ext, 1);
684                                                 $this->configs[$h]['mime'] = $this->set_mime($this->configs[$h][2]);
685                                                 $this->configs[$h]['hidden'] = is_file(SQUASHER_UPLOADS_DIR.$path.'/'.$base_name.'.hidden');
686                                                 //to prevent dates of 1-1-1970 we set te dates of the config file
687                                                 $this->configs[$h]['added'] = filectime($fsfilename);
688                                                 $this->configs[$h]['lastchange'] = filemtime($fsfilename);
689                                                 fclose($handle);
690                                                 $this->populate_stats($path, $h);
691                                                 //insert hash in db
692                                                 $this->update_hash($h, $path."/".$config[$i][2]);
693                                                 //check stats
694                                                 $this->check_stats($h);
695                                         }
696                                 }
697                         }
698                 }
699         }
700         closedir($hdir);
701 }
702
703 function check_stats($h) {
704         $db=$this->db;
705         $config = $this->get_config($h);
706         $count = @array_sum($config['stats']);
707         if ($config['status']=='Completed' && $count != $config[5]) {
708                 $filepath=$config['path'].'/'.$config[2];
709                 if ($this->history[$h]['completed']=="1") {
710                         //don't display broken file, remove it instead
711                         unlink(SQUASHER_UPLOADS_DIR.$config['path'].'/'.$config[2].'.Completed');
712                         unset($this->configs[$h]);
713
714                         if (!$count)
715                                 $count = 0;
716                         $m_subject = "Squasher Debug: File Removed";
717                         $m_body = "Upload removed: \n File: ".$config['path']."/".$config[2]." \n Status: ".$config['status']." \n Chunks: ".$count." out of ".$config[5];
718                         mail('jasper@netformatie.nl', $m_subject, $m_body, "From: support@netformatie.nl");
719                         
720                         log_event('debug', $filepath, $h, 'cleanup');
721                 } else {
722                         //do move
723                         rename(SQUASHER_UPLOADS_DIR.$config['path'].'/'.$config[2].'.Completed',
724                                SQUASHER_UPLOADS_DIR.$config['path'].'/'.$config[2].'.InProgress');
725                         $this->configs[$h]['status'] = 'InProgress';
726
727                         //mail n4m
728                         if (!$count)
729                                 $count = 0;
730                         $m_subject = "Squasher Debug: Upload Error";
731                         $m_body = "Upload error: \n File: ".$config['path']."/".$config[2]." \n Status: ".$config['status']." \n Chunks: ".$count." out of ".$config[5];
732                         mail('support@netformatie.nl', $m_subject, $m_body, "From: squasher@netformatie.nl");
733                         mail('jan@netformatie.nl', $m_subject, $m_body, "From: support@netformatie.nl");
734                         mail('joop@netformatie.nl', $m_subject, $m_body, "From: support@netformatie.nl");
735                         mail('jasper@netformatie.nl', $m_subject, $m_body, "From: support@netformatie.nl");
736
737                         //do sms
738                         //wget -o/dev/null "http://www.mollie.nl/xml/sms/?username=netformatie&password=SMSdolsi&originator=Netformatie&recipients=${ENGINEER}&message=${CALLERID}";
739
740                         //mail RO
741                         $ship = explode('/',$config['path']);
742                         if ($ship[2] == 'myas' || $ship[2] == 'myez' || $ship[2] == 'myrw')
743                                 mail('ro1@'.$ship[2].'.greenpeace.org','Squasher: '.$config[2].' resume request','The squasher server has detected an upload error. Please resume the squasher transmission for '.$config[2].' to correct this problem.',"From: support@netformatie.nl\nX-Priority: 1");
744                         log_event('debug', $filepath, $h, 'retry');
745
746                 }
747         } elseif ($config['status']=='Completed' && $count == $config[5]) {
748                 if ($this->history[$h]['completed']==0)
749                         $db->query("UPDATE file_hash SET completed = 1 WHERE md5_hash = '".$db->real_escape_string($h)."'");
750         }
751 }
752
753 function update_hash($hash, $path) {
754         $db=$this->db;
755         $check_hash_query = "select * from file_hash where md5_hash = '".$hash."'";
756         $check_hash_result = $db->query($check_hash_query);
757         if(mysqli_num_rows($check_hash_result) == 0) {
758                 $insert_hash_query = "INSERT INTO file_hash (md5_hash,file) values ('".$db->real_escape_string($hash)."','".$db->real_escape_string($path)."')";
759                 $db->query($insert_hash_query);
760         }
761 }
762
763 /* unused function */
764 /*
765 function path_to_arraystring($path, $arrayname) {
766         $path_values = explode('/', $path);
767         $return = $arrayname;
768         foreach ($path_values AS $key => $value) {
769                 if ($value != '.' && $value != '')
770                         $return.= "['".$value."']";
771         }
772         return $return;
773 } */
774
775 function populate_stats($path, $h) {
776         $db=$this->db;
777         /***
778         *       $config:: array
779         *       [0]     ->      versioncode
780         *       [1]     ->      date&time
781         *       [2]     ->      filename
782         *       [3]     ->      filesize
783         *       [4]     ->      chunksize
784         *       [5]     ->      chunkcount
785         *       [6]     ->      CRC32 checksum
786         ***/
787         $config = $this->configs[$h];
788
789         $q = "SELECT * FROM file_hash WHERE md5_hash = '".$db->real_escape_string($h)."'";
790         $r = $db->query($q);
791         $o = mysqli_fetch_object($r);
792         $validated_chunks = $o->validated_chunks;
793
794         if ($this->history[$h]['completed']=="1") {
795                 $file_part = $path."/SQ".zfill(1,6)."-".$config[2];
796                 if (!is_file(SQUASHER_UPLOADS_DIR.$file_part))
797                         $file_part = $path."/SQ".zfill(1,3)."-".$config[2];
798                 if (is_file(SQUASHER_UPLOADS_DIR.$file_part)) {
799                         $this->configs[$h]['added'] = filectime(SQUASHER_UPLOADS_DIR.$file_part);
800                         $file_part = $path."/SQ".zfill($config[5],6)."-".$config[2];
801                         if (!is_file(SQUASHER_UPLOADS_DIR.$file_part))
802                                 $file_part = $path."/SQ".zfill($config[5],3)."-".$config[2];
803                         if (is_file(SQUASHER_UPLOADS_DIR.$file_part))
804                                 $this->configs[$h]['lastchange'] = filemtime(SQUASHER_UPLOADS_DIR.$file_part);
805                         for ($i=1; $i<=$config[5]; $i++)
806                                 $this->configs[$h]['stats'][$i] = "1.00";
807                 } else {
808                         //failsafe voor verwijderde bestanden
809                         $db->query("UPDATE file_hash SET completed = 0 WHERE md5_hash = '".$db->real_escape_string($h)."'");
810                 }
811         } else {
812                 $keep_validating = true;
813                 for ($i=1; $i<=$config[5]; $i++) {
814                         if ($validated_chunks > $i) {
815                                 $this->configs[$h]['stats'][$i]="1.00";
816                         } else {
817                                 $file_part = $path."/SQ".zfill($i,6)."-".$config[2];
818                                 if (!is_file(SQUASHER_UPLOADS_DIR.$file_part))
819                                         $file_part = $path."/SQ".zfill($i,3)."-".$config[2];
820                                 if (is_file(SQUASHER_UPLOADS_DIR.$file_part)) {
821                                         $handle = fopen(SQUASHER_UPLOADS_DIR.$file_part, "rb");
822                                         $size_this = filesize(SQUASHER_UPLOADS_DIR.$file_part);
823                                         $added = filectime(SQUASHER_UPLOADS_DIR.$file_part);
824                                         $last_changed = filemtime(SQUASHER_UPLOADS_DIR.$file_part);
825                                         if ($this->configs[$h]['added'] > $added || !is_numeric($this->configs[$h]['added']))
826                                                 $this->configs[$h]['added'] = $added;
827                                         if ($this->configs[$h]['lastchange'] < $last_changed)
828                                                 $this->configs[$h]['lastchange'] = $last_changed;
829                                         if ($i != $config[5]) {
830                                                 $this->configs[$h]['stats'][$i] = number_format((1/$config[4])*$size_this, 2, '.', '');
831                                         //number_format((100/$config[4])*$size_this, 2, '.', '')."%";
832                                         }else{
833                                                 $this->configs[$h]['stats'][$i] = number_format((1/($config[3]-($config[4]*($config[5]-1))))*$size_this, 2, '.', '');
834                                                 //number_format((100/($config[3]-($config[4]*($config[5]-1))))*$size_this, 2, '.', '')."%";
835                                         }
836                                         fclose($handle);
837                                         if ($config[4] == $size_this && $keep_validating) {
838                                                 $validated_chunks = $i;
839                                         } else {
840                                                 $keep_validating = false;
841                                         }
842                                 } else {
843                                         $this->configs[$h]['stats'][$i] = "0.00";
844                                         //$this->configs[$h]['stats'][$i]="0.00%";
845
846                                 }
847                         }
848                 }
849                 $db->query("UPDATE file_hash SET validated_chunks = '".$db->real_escape_string($validated_chunks)."' WHERE md5_hash = '".$db->real_escape_string($h)."'");
850         }
851 }
852
853
854 /* unused function
855 function read_config($path, $filename) {
856         if (is_file($path."/".$filename.".InProgress")) {
857                 $config_handle = fopen($path."/".$filename.".InProgress", "r");
858                 $conf_path=$path."/".$filename.".InProgress";
859         } elseif (is_file($path."/".$filename.".Completed" )) {
860                 $config_handle = fopen($path."/".$filename.".Completed", "r");
861                 $conf_path=$path."/".$filename.".Completed";
862         } elseif (is_file($path."/".$filename.".Starting" )) {
863                 $config_handle = fopen($path."/".$filename.".Starting", "r");
864                 $conf_path=$path."/".$filename.".Starting";
865         } elseif (is_file($path."/".$filename.".Processed" )) {
866                 $config_handle = fopen($path."/".$filename.".Processed", "r");
867                 $conf_path=$path."/".$filename.".Processed";
868         } else {
869                 return "Not Found";
870         }
871         $config_content = fread($config_handle, filesize($conf_path));
872         fclose($config_handle);
873         $config = explode("\n", $config_content);
874
875         return $config;
876 }
877 */
878 //              print_r($config);
879 /*              $file_count = $config[5];
880                 $last=1;
881     for ($i=1; $i<=$file_count; $i++)
882     {
883         $file_part = $path."/SQ".zfill($i,6)."-".$filename;
884         if (is_file($file_part))
885        {
886
887         $handle = fopen($file_part, "rb");
888         $size_this = filesize($file_part);
889                                 //$stats[$i]=round((100/$config[4])*$size_this)."%";
890                                 if ((($size_this==$config[4] && ($last+1)==$i) )|| $i == $config[5]) {
891                                         $merged_file.=fread($handle, filesize($file_part));
892                                         $last = $i;
893                                 }
894         fclose($handle);
895        }
896      }
897      return $merged_file;
898      */
899
900 /**
901  * Outputs one file (echo)
902  * @param string $path Absolute path within SQUASHER_UPLOADS_DIR
903  * @param string $filename File name in $path
904  * @param bool $tovar Returns content rather than outputing it
905  * @return file content if $tovar; or void
906  */
907 function print_files($path, $filename, $tovar=false) {
908         $fsfilename = SQUASHER_UPLOADS_DIR.$path.'/'.$filename;
909         if (strpos($path.'/', '/ftp/')===0) {
910                 if (is_file($fsfilename)) {
911                         $handle = fopen($fsfilename, 'rb');
912                         while (!feof($handle))
913                         {
914                                 print(fread($handle, 1024));
915                                 ob_flush();
916                                 flush();
917                         }
918                 }
919         } else {
920                 if (is_file($fsfilename.'.InProgress'))
921                         $conf_path = $fsfilename.'.InProgress';
922                 elseif (is_file($fsfilename.'.Completed' ))
923                         $conf_path = $fsfilename.'.Completed';
924                 elseif (is_file($fsfilename.'.Starting' ))
925                         $conf_path = $fsfilename.'.Starting';
926                 elseif (is_file($fsfilename.'.Processed' ))
927                         $conf_path = $fsfilename.'.Processed';
928                 else
929                         return 'Not Found';
930                 $config_handle = fopen($conf_path, 'r');
931                 $config_content = fread($config_handle, filesize($conf_path));
932                 fclose($config_handle);
933                 $config = explode("\n",$config_content);
934 //              print_r($config);
935                 $file_count = $config[5];
936                 $last = 0;
937                 $last_part_size = ( $config[3] - ( ( $config[5] -1 ) * $config[4] ) );
938                 for ($i=0;$i<=$file_count;$i++)
939                 {
940                         $file_part = SQUASHER_UPLOADS_DIR.$path."/SQ".zfill($i,6)."-".$filename;
941                         if (!is_file($file_part))
942                                 $file_part = $path."/SQ".zfill($i,3)."-".$filename;
943                         if (is_file($file_part))
944                         {
945                                 $handle = fopen($file_part, "rb");
946                                 $size_this = filesize($file_part);
947                                 if ( ( ( $size_this==$config[4] ) && ( ($last+1)==$i ) ) || ( ( $i == $config[5] ) && ( $size_this==$last_part_size ) && ( ($last+1)==$i ) ) ) {
948                                         if ($tovar) {
949                                                 $merged_file.=fread($handle, $size_this);
950                                                 $last = $i;
951                                         } else {
952                                                 while (!feof($handle))
953                                                 {
954                                                         print(fread($handle, 4096));
955                                                 #       @ob_flush();
956                                                 #       @flush();
957                                                 }
958                                                 $last = $i;
959                                         }
960                                 }
961                                 fclose($handle);
962                         }
963                 }
964                 if ($tovar)
965                         return $merged_file;
966         }
967 }
968
969 /* unused function */
970 /*
971 function check_md5($h) {
972         $return = false;
973         $config = $this->configs[$h];
974         $var = $this->print_files($config['path'], $config[2], true);
975         $hash = md5($var);
976         if ($hash==$config[6])
977                 $return=true;
978
979         return $return;
980 } */
981
982 /* unused function */
983 /*
984 function file_crc($file_string) {
985         //$file_string = file_get_contents($file);
986
987         $crc = crc32($file_string);
988         return sprintf("%u\n", $crc);
989 } */
990
991 /* unused function */
992 /*
993 function file_crc_debug($file) {
994         $file_string = file_get_contents($file);
995
996         $crc = crc32($file_string);
997         return sprintf("%u\n", $crc);
998 } */
999
1000 /**
1001  * Delete one file
1002  *
1003  * @param string $h Md5 hash of the file path, in lower case
1004  * @param array $s Session credidentials
1005  */
1006 function delete_file($h, $s) {
1007         $db=$this->db;
1008         $request = $this->get_config($h);
1009         $filepath = $request['path'].'/'.$request[2];
1010         if (strpos($request['path'], '/ftp/')===0) {
1011                 #remove file
1012                 $fsfilepath = SQUASHER_UPLOADS_DIR.$filepath;
1013                 if (is_file($fsfilepath))
1014                         @unlink($fsfilepath);
1015                 if (is_file($fsfilepath.'.hidden'))
1016                         @unlink($fsfilepath.'.hidden');
1017         } else {
1018                 $fspath = SQUASHER_UPLOADS_DIR.$request['path'];
1019                 #remove fileparts
1020                 for ($i=0;$i<=$request[5];$i++) {
1021                         $part_six   = $fspath.'/SQ'.zfill($i,6).'-'.$request[2];
1022                         $part_three = $fspath.'/SQ'.zfill($i,3).'-'.$request[2];
1023                         if (is_file($part_six))
1024                                 @unlink($part_six);
1025                         if (is_file($part_three))
1026                                 @unlink($part_three);
1027                 }
1028                 #remove config file
1029                 if (is_file($fspath.'/'.$request[2].'.hidden'))
1030                         @unlink($fspath.'/'.$request[2].'.hidden');
1031                 if (is_file($fspath.'/'.$request[2].'.Completed'))
1032                         @unlink($fspath.'/'.$request[2].'.Completed');
1033                 if (is_file($fspath.'/'.$request[2].'.InProgress'))
1034                         @unlink($fspath.'/'.$request[2].'.InProgress');
1035                 if (is_file($fspath.'/'.$request[2].'.Processed'))
1036                         @unlink($fspath.'/'.$request[2].'.Processed');
1037                 if (is_file($fspath.'/'.$request[2].'.Starting'))
1038                         @unlink($fspath.'/'.$request[2].'.Starting');
1039         }
1040
1041         #Update DB
1042         $q = "DELETE FROM file_hash WHERE md5_hash = '".$db->real_escape_string($h)."'";
1043         $db->query($q);
1044
1045         log_event('delete', $filepath, $h);
1046
1047         #Send debug mail
1048         $m_name = $s['user_name'];
1049         $m_subject = "Squasher Debug: File Deleted by {$m_name}";
1050         $m_body = "File Deleted: \n Requested by: {$m_name} \n File: {$filepath}";
1051         mail('jasper@netformatie.nl', $m_subject, $m_body, "From: support@netformatie.nl");
1052 }
1053
1054 /* unused debug function (echo / print_r)
1055 function show_files() {
1056
1057         $path = "./uploads/";
1058
1059         if ($dir = opendir($path)) {
1060                 $i = 1;
1061                 $last = 1;
1062                 $files = array();
1063                 $files_merged = array();
1064                 while (false !== ($file = readdir($dir)))
1065                 {
1066                         if (($file !== ".") && ($file !== ".."))
1067                         {
1068                                 $filename = $path.$file;
1069                                 $handle = fopen($filename, "rb");
1070                                 $size_this = filesize($filename);
1071                                 if ($i==1)
1072                                         $size_first = $size_this;
1073                                 $filecontent = fread($handle, filesize($filename));
1074                                 $files[$i++] = $filename;
1075                                 $files_merged[$file_base][]=$filename;
1076                                 fclose($handle);
1077                         }
1078                 }
1079         }
1080         echo "<pre>";
1081         print_r($files);
1082         print_r($files_merged);
1083         echo "</pre>";
1084 }
1085 */
1086
1087 /**
1088  * Get mime-type from filename
1089  *
1090  * Defaults to 'application/octet-stream'
1091  *
1092  * @param string $filename The filename with an extension
1093  * @return string mime type
1094  */
1095 function set_mime($filename) {
1096         $ext_arr = explode('.', $filename);
1097         $ext = strtolower(array_pop($ext_arr));
1098         switch($ext) {
1099                 case 'avi':
1100                         $mime = 'video/avi';
1101                         break;
1102                 case 'mpeg':
1103                 case 'mpg':
1104                         $mime = 'video/mpeg';                                   //MPEG Video
1105                         break;
1106                 case 'exe':
1107                 case 'bat':
1108                 case 'doc':
1109                 case 'xls':
1110                         $mime = 'application/octet-stream';
1111                         break;
1112                 case 'gif':
1113                         $mime = 'image/gif';                                    //GIF Image
1114                         break;
1115                 case 'jpg':
1116                 case 'jpeg':
1117                         $mime = 'image/jpeg';                                   //JPEG Image
1118                         break;
1119                 case 'png':
1120                         $mime = 'image/png';                                    //PNG Image
1121                         break;
1122                 case 'wav':
1123                 case 'wave':
1124                         $mime = 'audio/wav';                                    //WAV Audio
1125                         break;
1126                 case 'mp3':
1127                         $mime = 'audio/mpeg';                                   //MP3 Audio
1128                         break;
1129                 case 'mov':
1130                         $mime = 'video/mov';                                    //Quicktime Video
1131                         break;
1132                 case 'wmv':
1133                         $mime = 'video/x-ms-wmv';                       //Windows WMV video
1134                         break;
1135                 case 'wma':
1136                         $mime = 'audio/x-ms-wma';                       //Windows WMA audio
1137                         break;
1138                 case 'rm':
1139                         $mime = 'audio/x-realaudio';    //RealPlayer Audio/Video (.rm)
1140                         break;
1141                 case 'ram':
1142                         $mime = 'audio/x-pn-realaudio'; //RealPlayer Audio/Video (.ram)
1143                         break;
1144                 case 'pdf':
1145                         $mime = 'application/pdf';              //PDF Document
1146                         break;
1147                 case 'doc':
1148                         $mime = 'application/msword';   //MS Word .doc file
1149                         break;
1150                 case 'zip':
1151                         $mime = 'application/zip';              //Zip File
1152                         break;
1153                 default:
1154                         $mime = 'application/octet-stream';
1155                         break;
1156         }
1157         //$return['mime']=$mime;
1158         //$return['ext']=$ext;
1159
1160         return $mime;
1161 }
1162
1163 }
1164 // vim: syntax=php ts=4 sw=4 sts=4 sr noet
1165 ?>