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