File.php
Go to the documentation of this file.
00001 <?PHP 00002 00003 # 00004 # FILE: File.php 00005 # 00006 # Copyright 2010 Edward Almasy and Internet Scout 00007 # http://scout.wisc.edu 00008 # 00009 00010 00011 class File { 00012 00013 # ---- PUBLIC INTERFACE -------------------------------------------------- 00014 00015 # status codes (set by constructor and returned by File::Status()) 00016 const FILESTAT_OK = 0; 00017 const FILESTAT_COPYERROR = 1; 00018 const FILESTAT_PARAMERROR = 2; 00019 const FILESTAT_ZEROLENGTH = 3; 00020 const FILESTAT_DOESNOTEXIST = 4; 00021 const FILESTAT_UNREADABLE = 5; 00022 00023 # object constructor 00024 function File($IdOrFileName, $ResourceId = NULL, $FieldId = NULL, 00025 $DesiredFileName = NULL, $CheckFileLength = TRUE) 00026 { 00027 # assume constructor will succeed 00028 $this->Status = self::FILESTAT_OK; 00029 00030 # get our own database handle 00031 $DB = new Database(); 00032 $this->DB = $DB; 00033 00034 # if ID supplied 00035 if (is_int($IdOrFileName)) 00036 { 00037 # set file ID from supplied value 00038 $this->Id = intval($IdOrFileName); 00039 00040 # load file info from database 00041 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id); 00042 $this->DBFields = $DB->FetchRow(); 00043 } 00044 # else if file name and resource ID and field ID supplied 00045 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL)) 00046 { 00047 # if file does not exist 00048 $TempFileName = $IdOrFileName; 00049 if (!file_exists($TempFileName) || !is_readable($TempFileName)) 00050 { 00051 # set status indicating appropriate error 00052 $this->Status = file_exists($TempFileName) 00053 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE; 00054 } 00055 else 00056 { 00057 # if we were asked to check file length and file was zero length 00058 $FileLength = filesize($TempFileName); 00059 if ($CheckFileLength && !$FileLength) 00060 { 00061 # set status indicating zero length file 00062 $this->Status = self::FILESTAT_ZEROLENGTH; 00063 } 00064 else 00065 { 00066 # generate secret string (used to protect from unauthorized download) 00067 srand((double)microtime() * 1000000); 00068 $SecretString = sprintf("%04X", rand(1, 30000)); 00069 00070 # attempt to get file type 00071 if (function_exists("finfo_open")) 00072 { 00073 $FInfoHandle = finfo_open(FILEINFO_MIME); 00074 $FileType = finfo_file($FInfoHandle, $TempFileName); 00075 finfo_close($FInfoHandle); 00076 } 00077 else if (function_exists("mime_content_type")) 00078 { 00079 # mime_content_type has been deprecated, but it may be 00080 # the only way to get the mimetype for PHP < 5.3 00081 $FileType = mime_content_type($TempFileName); 00082 } 00083 else 00084 { 00085 $FileType = ""; 00086 } 00087 00088 # add file info to database 00089 $BaseFileName = $DesiredFileName 00090 ? basename($DesiredFileName) : basename($TempFileName); 00091 $DB->Query("INSERT INTO Files" 00092 ." (ResourceId, FieldId, FileName, FileLength, FileType," 00093 ." SecretString)" 00094 ." VALUES (" 00095 .intval($ResourceId).", " 00096 .intval($FieldId).", " 00097 ."'".addslashes($BaseFileName)."', " 00098 .$FileLength.", " 00099 ."'".$FileType."', " 00100 ."'".$SecretString."')"); 00101 00102 # retrieve ID of new file 00103 $this->Id = $DB->LastInsertId("Files"); 00104 00105 # load file info back in from database 00106 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id); 00107 $this->DBFields = $DB->FetchRow(); 00108 00109 # copy file to storage 00110 $CopySucceeded = copy($IdOrFileName, $this->GetNameOfStoredFile()); 00111 00112 # if copy failed 00113 if (!$CopySucceeded) 00114 { 00115 # remove file info from database 00116 $DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id); 00117 00118 # set status indicating constructor failed 00119 $this->Status = self::FILESTAT_COPYERROR; 00120 } 00121 } 00122 } 00123 } 00124 else 00125 { 00126 # set status indicating constructor failed 00127 $this->Status = self::FILESTAT_PARAMERROR; 00128 } 00129 } 00130 00131 # return object status (used to report errors occurring in constructor) 00132 function Status() { return $this->Status; } 00133 00134 # get various attributes 00135 function Id() { return $this->Id; } 00136 function Name() { return $this->DBFields["FileName"]; } 00137 function GetLength() { return $this->DBFields["FileLength"]; } 00138 function GetType() { return $this->DBFields["FileType"]; } 00139 00140 # get/set various attributes 00141 function Comment($NewValue = DB_NOVALUE) 00142 { return $this->UpdateValue("FileComment", $NewValue); } 00143 function FieldId($NewValue = DB_NOVALUE) 00144 { return $this->UpdateValue("FieldId", $NewValue); } 00145 function ResourceId($NewValue = DB_NOVALUE) 00146 { return $this->UpdateValue("ResourceId", $NewValue); } 00147 00148 # get MIME type (defaults to "application/octet-stream" if not available) 00149 function GetMimeType() 00150 { 00151 return strlen($this->GetType()) 00152 ? $this->GetType() : "application/octet-stream"; 00153 } 00154 00155 # get link for downloading file 00156 function GetLink() 00157 { 00158 return "index.php?P=DownloadFile&Id=".$this->Id; 00159 } 00160 00161 # delete file (other methods are invalid after calling this!) 00162 function Delete() 00163 { 00164 # remove file entry from DB 00165 $this->DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id); 00166 00167 # delete file 00168 $FileName = $this->GetNameOfStoredFile(); 00169 if (file_exists($FileName)) 00170 { 00171 unlink($FileName); 00172 } 00173 } 00174 00175 # retrieve actual name of stored file 00176 function GetNameOfStoredFile() 00177 { 00178 return sprintf("FileStorage/%06d-%s-%s", 00179 $this->Id, $this->DBFields["SecretString"], $this->Name()); 00180 } 00181 00182 00183 # ---- PRIVATE INTERFACE ------------------------------------------------- 00184 00185 private $DB; 00186 private $Status; 00187 private $Id; 00188 private $DBFields; 00189 00190 # convenience function to supply parameters to Database->UpdateValue() 00191 private function UpdateValue($FieldName, $NewValue) 00192 { 00193 return $this->DB->UpdateValue("Files", $FieldName, $NewValue, 00194 "FileId = ".intval($this->Id), 00195 $this->DBFields, TRUE); 00196 } 00197 } 00198 00199 00200 ?>