00001 <?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}
00002 # streber - a php5 based project management system (c) 2005-2007 / www.streber-pm.org
00003 # Distributed under the terms and conditions of the GPL as stated in lang/license.html
00004
00017 class File extends DbProjectItem
00018 {
00019 public $tmp_filename=""; # filename relative to index.php to which file is moved unti insert()
00020
00021
00022 function __construct ($id_or_array=false)
00023 {
00024 global $g_file_fields;
00025 $this->fields= &$g_file_fields;
00026
00027 parent::__construct($id_or_array);
00028 if(!$this->type) {
00029 $this->type= ITEM_FILE;
00030 }
00031 }
00032
00036 static function initFields()
00037 {
00038 global $g_file_fields;
00039 $g_file_fields= array();
00040 addProjectItemFields(&$g_file_fields);
00041
00042 foreach(array(
00043 new FieldInternal(array( 'name'=>'id',
00044 'default'=>0,
00045 'in_db_object'=>1,
00046 'in_db_item'=>1,
00047 )),
00048 new FieldString(array( 'name'=>'name',
00049 'title'=>__('Name'),
00050 'view_in_forms'=>true
00051 )),
00052 new FieldString(array( 'name'=>'org_filename',
00053 'view_in_forms'=>false
00054 )),
00055
00065 new FieldString(array( 'name'=>'tmp_filename',
00066 'view_in_forms'=>false
00067 )),
00068
00069 new FieldString(array( 'name'=>'tmp_dir',
00070 'view_in_forms'=>false
00071 )),
00072
00073 new FieldString(array( 'name'=>'mimetype',
00074 'view_in_forms'=>false
00075 )),
00076 new FieldInternal(array( 'name'=>'status',
00077 'view_in_forms'=>false
00078 )),
00079 new FieldInt(array( 'name'=>'filesize',
00080 'view_in_forms'=>false
00081 )),
00082 new FieldInt(array( 'name'=>'version',
00083 'view_in_forms'=>false,
00084 'default'=>1,
00085 )),
00086
00092 new FieldBool(array( 'name'=>'is_image',
00093 'view_in_forms' =>false,
00094 'default' =>0
00095 )),
00096
00101 new FieldBool(array( 'name'=>'is_latest',
00102 'view_in_forms' =>false,
00103 'default' =>1
00104 )),
00105
00110 new FieldString(array( 'name'=>'thumbnail',
00111 'view_in_forms'=>false
00112 )),
00113
00114 new FieldInternal(array( 'name'=>'parent_item',
00115 'view_in_forms'=>false
00116 )),
00117
00121 new FieldInternal(array( 'name'=>'org_file',
00122 'view_in_forms'=>false
00123 )),
00124
00125
00126 new FieldText(array( 'name'=>'description',
00127 'title'=>__('Description'),
00128
00129 )),
00130 ) as $f) {
00131 $g_file_fields[$f->name]=$f;
00132 }
00133 }
00134
00135
00141 static function getById($id)
00142 {
00143 $c= new File($id);
00144 if($c->id) {
00145 return $c;
00146 }
00147 return NULL;
00148 }
00149
00150
00151 static function getVisibleById($id)
00152 {
00153 if($c= File::getById($id)) {
00154 if($c->id) {
00155 if($p= Project::getById($c->project)) {
00156 if($p->validateViewItem($c,false)) {
00157 return $c;
00158 }
00159 }
00160 }
00161 }
00162 return NULL;
00163 }
00164
00165
00169 static function getEditableById($id)
00170 {
00171 if($c= File::getById($id)) {
00172 if($p= Project::getById($c->project)) {
00173 if($p->validateEditItem($c,false)) {
00174 return $c;
00175 }
00176 }
00177 }
00178 return NULL;
00179 }
00180
00181
00182
00183
00190 static function &getAll( $args=NULL)
00191 {
00192 global $auth;
00193 $prefix = confGet('DB_TABLE_PREFIX');
00194
00195 ### default params ###
00196 $project = NULL;
00197 $latest_only = true;
00198 $order_by = "name";
00199 $status_min = STATUS_UNDEFINED;
00200 $status_max = STATUS_CLOSED;
00201 $visible_only = true; # use project rights settings
00202 $alive_only = true; # ignore deleted
00203 $parent_item = NULL; #
00204 $images_only = false;
00205 $date_min = NULL;
00206 $date_max = NULL;
00207 $org_file = NULL;
00208 $id = NULL;
00209 $created_by = NULL;
00210
00211 ### filter params ###
00212 if($args) {
00213 foreach($args as $key=>$value) {
00214 if(!isset($$key) && !is_null($$key) && !$$key==="") {
00215 trigger_error("unknown parameter",E_USER_NOTICE);
00216 }
00217 else {
00218 $$key= $value;
00219 }
00220 }
00221 }
00222
00223 $str_project= $project
00224 ? 'AND i.project=' . intval($project)
00225 : '';
00226
00227 $str_project2= $project
00228 ? 'AND upp.project=' . intval($project)
00229 : '';
00230
00231 $str_is_alive= $alive_only
00232 ? 'AND i.state=' . ITEM_STATE_OK
00233 : '';
00234
00235
00236 $str_date_min= $date_min
00237 ? "AND i.modified >= '" . asCleanString($date_min) . "'"
00238 : '';
00239
00240 $str_date_max= $date_max
00241 ? "AND i.modified <= ' ". asCleanString($date_max) . "'"
00242 : '';
00243
00244 $str_is_image= $images_only
00245 ? 'AND f.is_image!=0'
00246 : '';
00247
00248 $str_latest_only= $latest_only
00249 ? 'AND f.is_latest!=0'
00250 : '';
00251
00252 $str_created_by= $created_by
00253 ? 'AND i.modified_by ='. intval($created_by)
00254 : '';
00255
00256 $str_parent_item= !is_null($parent_item)
00257 ? 'AND f.parent_item=' . intval($parent_item)
00258 : '';
00259
00260 $str_org_file= $org_file
00261 ? "AND f.org_file = '" . intval($org_file) . "'"
00262 : "";
00263
00264 $str_id = $id
00265 ? "AND f.id = " . intval($id)
00266 : "";
00267
00268 if ($auth->cur_user->user_rights & RIGHT_VIEWALL)
00269 {
00270 $str_projectperson = "";
00271 }
00272 else
00273 {
00274 $str_projectperson = "AND upp.person = {$auth->cur_user->id}";
00275 }
00276
00277 if($visible_only) {
00278 $str_query=
00279 "SELECT DISTINCT i.*, f.* from {$prefix}item i, {$prefix}file f, {$prefix}projectperson upp
00280 WHERE
00281 i.type = '".ITEM_FILE."'
00282 $str_project
00283 $str_projectperson
00284 $str_project2
00285
00286 $str_is_alive
00287 AND ( i.pub_level >= upp.level_view
00288 OR
00289 i.created_by = {$auth->cur_user->id}
00290 )
00291
00292 AND i.id = f.id
00293 $str_id
00294 $str_created_by
00295 $str_is_image
00296 $str_parent_item
00297 $str_org_file
00298 $str_latest_only
00299 AND f.status >= $status_min
00300 AND f.status <= $status_max
00301 $str_date_max
00302 $str_date_min
00303
00304 ". getOrderByString($order_by)
00305 ;
00306 }
00307 ### show all ###
00308 else {
00309 $str_query=
00310 "SELECT i.*, f.* from {$prefix}item i, {$prefix}file f
00311 WHERE
00312 i.type = '".ITEM_FILE."'
00313 $str_project
00314 $str_is_alive
00315
00316 AND i.id = f.id
00317 $str_id
00318 $str_created_by
00319 $str_parent_item
00320 $str_latest_only
00321 AND f.status >= $status_min
00322 AND f.status <= $status_max
00323 $str_org_file
00324 $str_date_max
00325 $str_date_min
00326
00327 ". getOrderByString($order_by)
00328 ;
00329 }
00330
00331 $dbh = new DB_Mysql;
00332 $sth= $dbh->prepare($str_query);
00333
00334 $sth->execute("",1);
00335 $tmp=$sth->fetchall_assoc();
00336 $files=array();
00337 require_once(confGet('DIR_STREBER') . 'db/class_file.inc.php');
00338 foreach($tmp as $t) {
00339 $file=new File($t);
00340 $files[]=$file;
00341 }
00342 return $files;
00343 }
00344
00348 public function getOriginal()
00349 {
00350 if($this->org_file == 0) {
00351 return $this;
00352 }
00353 if($org_file= File::getVisibleById($this->org_file)) { # NOTE: this is slow!
00354 return $org_file;
00355 }
00356 else {
00357 trigger_error("failed to get original file of $file->id", E_USER_WARNING);
00358 return NULL;
00359 }
00360 }
00361
00365 public function getLatest()
00366 {
00367 if($this->is_latest) {
00368 return $this;
00369 }
00370 $org_file= $this->org_file;
00371
00372 if($org_file == 0) {
00373 $org_file= $this->id;
00374 }
00375
00376 if(!$project= Project::getVisibleById($this->project)) {
00377 trigger_error("file $file->id has no project", E_USER_WARNING);
00378 return NULL;
00379 }
00380
00381 $files= File::getAll(array(
00382 'latest_only' => true,
00383 'org_file' => $org_file,
00384 'project' => $project->id,
00385 ));
00386 if(count($files) > 1) {
00387
00388 foreach($files as $f) {
00389 $list[]=$f->id;
00390 }
00391
00392 trigger_error("unexpected number (". join(",",$list) .") of latest files for file id $this->id", E_USER_WARNING);
00393 $files[0];
00394 }
00395
00396 return $files[0];
00397 }
00398
00399
00409 public static function getUploaded()
00410 {
00411 global $auth;
00412
00413 $upload_id= 'userfile'; # id of upload field
00414
00415 switch ($_FILES[$upload_id]['error']) {
00416 case UPLOAD_ERR_OK:
00417 break;
00418 case UPLOAD_ERR_INI_SIZE:
00419 trigger_error("The uploaded file exceeds the upload_max_filesize directive (".ini_get("upload_max_filesize").") in php.ini.", E_USER_NOTICE);
00420 break;
00421 case UPLOAD_ERR_FORM_SIZE:
00422 trigger_error("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.", E_USER_NOTICE);
00423 break;
00424 case UPLOAD_ERR_PARTIAL:
00425 trigger_error("The uploaded file was only partially uploaded.", E_USER_NOTICE);
00426 break;
00427 case UPLOAD_ERR_NO_FILE:
00428 trigger_error("No file was uploaded.", E_USER_NOTICE);
00429 break;
00430 case UPLOAD_ERR_NO_TMP_DIR:
00431 trigger_error("Missing a temporary folder.", E_USER_NOTICE);
00432 break;
00433 case UPLOAD_ERR_CANT_WRITE:
00434 trigger_error("Failed to write file to disk", E_USER_NOTICE);
00435 break;
00436 default:
00437 trigger_error("Unknown File Error", E_USER_NOTICE);
00438 }
00439
00440 $org_filename= $_FILES[$upload_id]['name'];
00441 $filesize= $_FILES[$upload_id]['size'];
00442
00443 if(!$filesize || $org_filename == "") {
00444 #trigger_error("there was nothing to upload", E_USER_NOTICE);
00445 return NULL;
00446 }
00447
00448 $tmp_filename = preg_replace("/[^a-z0-9-._]/i", '_', $org_filename);
00449
00450 ### figure mimetype ###
00451 {
00452 $mimetype = $_FILES[$upload_id]['type'];
00453 }
00454
00455 ### is an image ? ###
00456
00457 ### check temporary upload dir ###
00458 $upload_dir = confGet('DIR_TEMP') . 'uploads';
00459
00460
00461 if(!file_exists($upload_dir)) {
00462 if(!mkdir($upload_dir)) {
00463 trigger_error("could not create temporary file upload directory: '$upload_dir'");
00464 return NULL;
00465 }
00466 }
00467
00468 if(move_uploaded_file($_FILES[$upload_id]['tmp_name'], $upload_dir."/".$tmp_filename)) {
00469
00470 $f= new File(array(
00471 'id' =>0,
00472 'name' => $org_filename,
00473 'org_filename' => $org_filename,
00474 'tmp_filename' => $tmp_filename,
00475 'mimetype' => $mimetype,
00476 'filesize' => $filesize,
00477 ));
00478 return $f;
00479
00480 }
00481 else {
00482 #print "Possible file upload attack! Here's some debugging info:\n";
00483 #print_r($_FILES);
00484 trigger_error("failure getting uploaded file-object", E_USER_NOTICE);
00485 return NULL;
00486 }
00487 }
00488
00489
00490
00498 public function insert()
00499 {
00500 $upload_filepath= confGet('DIR_TEMP') . 'uploads/' . $this->tmp_filename;
00501 if(!file_exists($upload_filepath)) {
00502 trigger_error("Uploaded field no longer exists in $upload_filepath", E_USER_WARNING);
00503 return NULL;
00504 }
00505 if(!file_exists(confGet('DIR_FILES'))) {
00506 trigger_error("Directory for files '" . confGet('DIR_FILES') . "' does not exists", E_USER_WARNING);
00507 return NULL;
00508 }
00509
00510 ### create project directory ###
00511 $this->tmp_dir= "prj{$this->project}";
00512 if(! file_exists(confGet('DIR_FILES') . $this->tmp_dir)) {
00513 if( !mkdir(confGet('DIR_FILES') . $this->tmp_dir, 0777)) {
00514 trigger_error("could not create target directory for uploaded file '" .confGet('DIR_FILES') . $this->tmp_dir. "'", E_USER_WARNING);
00515 return NULL;
00516 }
00517 }
00518
00525 if(! parent::insert() || !$this->id ) {
00526 trigger_error("inserting file object failed");
00527 return NULL;
00528 }
00529 $this->tmp_filename= $this->id .".".$this->tmp_filename;
00530
00531 ### use original function to write to Db
00532 parent::update();
00533
00534 ### move file ###
00535 if(!rename($upload_filepath, confGet('DIR_FILES') . $this->tmp_dir . $this->tmp_filename)) {
00536 trigger_error("could not move uploaded file from '$upload_filepath' to '" .confGet('DIR_FILES') . $this->tmp_dir . $this->tmp_filename. "'", E_USER_WARNING);
00537
00538 ### remove invalid database entry ###
00539 $this->DeleteFromDb();
00540 return NULL;
00541 }
00542
00543 return true;
00544 }
00545
00546
00547
00551 public function download()
00552 {
00553 $filepath= confGet('DIR_FILES') . $this->tmp_dir . $this->tmp_filename;
00554
00555 if(file_exists($filepath)) {
00556 header('Content-Length: ' . filesize($filepath));
00557 header('Content-Type: ' . $this->mimetype);
00558 header("Content-Disposition: attachment; filename=\"$this->org_filename\"");
00559 readfile_chunked($filepath);
00560 }
00561 else {
00562 trigger_error("can not find file '$filepath'");
00563 }
00564 }
00565
00566 public function view()
00567 {
00568 $filepath= confGet('DIR_FILES') . $this->tmp_dir . $this->tmp_filename;
00569
00570 if(file_exists($filepath)) {
00571 header('Content-Length: ' . filesize($filepath));
00572 header('Content-Type: ' . $this->mimetype);
00573 header("Content-Disposition: inline; filename=\"$this->org_filename\"");
00574 header('Last-Modified: ' . gmdate("D, j M Y G:i:s T", strToClientTime($this->modified)));
00575 readfile_chunked($filepath);
00576 }
00577 else {
00578 log_message("file::download($this->id) can not find file '$filepath'",LOG_MESSAGE_MISSING_FILES);
00579 }
00580 }
00581
00582 public function viewAsImage($max_size = 0)
00583 {
00584 $filepath= confGet('DIR_FILES') . $this->tmp_dir . $this->tmp_filename;
00585
00586 if(file_exists($filepath)) {
00587
00588 list($width, $height, $type, $attr) = getimagesize($filepath);
00589 if($max_size && ($width > $max_size || $height > $max_size)) {
00590 $ratio= $width/$height;
00591 if($width > $height) {
00592 $new_width= $max_size;
00593 $new_height= $max_size / $ratio;
00594 }
00595 else {
00596 $new_height= $max_size;
00597 $new_width= $max_size * $ratio;
00598 }
00599
00600 ### rescale with gd ###
00601 if(function_exists('imagecreatetruecolor')) {
00602 if($this->mimetype == 'image/jpeg'
00603 ||
00604 $this->mimetype == 'image/jpg'
00605 ||
00606 $this->mimetype == 'image/pjpeg'
00607 ) {
00608 header('Content-Type: ' . 'image/jpeg');
00609 header("Cache-Control: public");
00610 header("Last-Modified: ". gmdate('r',strToClientTime($this->modified)));
00611
00612 $image= imagecreatefromjpeg($filepath);
00613 $image_new= imagecreatetruecolor($new_width,$new_height) or die("Cannot Initialize new GD image stream");
00614 if(imagecopyresampled(
00615 $image_new, #resource dst_im,
00616 $image, #resource src_im,
00617 0, #int dstX,
00618 0, #int dstY,
00619 0, #int srcX,
00620 0, #int srcY,
00621 $new_width, #int dstW,
00622 $new_height, #int dstH,
00623 $width, #int srcW,
00624 $height #int srcH
00625 )) {
00626 imagejpeg($image_new);
00627 }
00628 else {
00629 imagejpeg($image);
00630 }
00631 return;
00632 }
00633 else if($this->mimetype == 'image/png') {
00634 header('Content-Type: ' . 'image/png');
00635 header("Cache-Control: public");
00636 header("Last-Modified: ". gmdate('r',strToClientTime($this->modified)));
00637
00638 #header("Expires: Thu, 01 Dec 2010 16:00:00 GMT");
00639
00640 $image= imagecreatefrompng($filepath);
00641 $image_new= imagecreatetruecolor($new_width,$new_height) or die("Cannot Initialize new GD image stream");
00642 if(imagecopyresampled(
00643 $image_new, #resource dst_im,
00644 $image, #resource src_im,
00645 0, #int dstX,
00646 0, #int dstY,
00647 0, #int srcX,
00648 0, #int srcY,
00649 $new_width, #int dstW,
00650 $new_height, #int dstH,
00651 $width, #int srcW,
00652 $height #int srcH
00653 )) {
00654 imagejpeg($image_new);
00655 }
00656 else {
00657 imagejpeg($image);
00658 }
00659 return;
00660 }
00661 else if($this->mimetype == 'image/gif') {
00662 header('Content-Type: ' . 'image/gif');
00663 header("Cache-Control: public");
00664 header("Last-Modified: ". gmdate('r',strToClientTime($this->modified)));
00665 $image= imagecreatefromgif($filepath);
00666 $image_new= imagecreatetruecolor($new_width,$new_height) or die("Cannot Initialize new GD image stream");
00667 if(imagecopyresampled(
00668 $image_new, #resource dst_im,
00669 $image, #resource src_im,
00670 0, #int dstX,
00671 0, #int dstY,
00672 0, #int srcX,
00673 0, #int srcY,
00674 $new_width, #int dstW,
00675 $new_height, #int dstH,
00676 $width, #int srcW,
00677 $height #int srcH
00678 )) {
00679 imagejpeg($image_new);
00680 }
00681 else {
00682 imagejpeg($image);
00683 }
00684 return;
00685 }
00686 else {
00687 return NULL;
00688 }
00689 }
00690 }
00691
00692
00693 header('Content-Length: ' . filesize($filepath));
00694 header('Content-Type: ' . $this->mimetype);
00695 header("Content-Disposition: inline; filename=$this->org_filename");
00696 header('Last-Modified: ' . gmdate("D, j M Y G:i:s T", strToClientTime($this->modified)));
00697 readfile_chunked($filepath);
00698 }
00699 else {
00700 log_message("file::viewAsImage($this->id) can not find file '$filepath'",LOG_MESSAGE_MISSING_FILES);
00701 }
00702 }
00703 }
00704 File::initFields();
00705
00706 ?>