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 $FileType = ""; 00072 if (function_exists("finfo_open")) 00073 { 00074 $FInfoHandle = finfo_open(FILEINFO_MIME); 00075 00076 if ($FInfoHandle) 00077 { 00078 $FInfoMime = finfo_file($FInfoHandle, $TempFileName); 00079 finfo_close($FInfoHandle); 00080 00081 if ($FInfoMime) 00082 { 00083 $FileType = $FInfoMime; 00084 } 00085 } 00086 } 00087 else if (function_exists("mime_content_type")) 00088 { 00089 # mime_content_type has been deprecated, but it may be 00090 # the only way to get the mimetype for PHP < 5.3 00091 $MimeType = mime_content_type($TempFileName); 00092 00093 if ($MimeType) 00094 { 00095 $FileType = $MimeType; 00096 } 00097 } 00098 00099 # add file info to database 00100 $BaseFileName = $DesiredFileName 00101 ? basename($DesiredFileName) : basename($TempFileName); 00102 $DB->Query("INSERT INTO Files" 00103 ." (ResourceId, FieldId, FileName, FileLength, FileType," 00104 ." SecretString)" 00105 ." VALUES (" 00106 .intval($ResourceId).", " 00107 .intval($FieldId).", " 00108 ."'".addslashes($BaseFileName)."', " 00109 .$FileLength.", " 00110 ."'".$FileType."', " 00111 ."'".$SecretString."')"); 00112 00113 # retrieve ID of new file 00114 $this->Id = $DB->LastInsertId("Files"); 00115 00116 # load file info back in from database 00117 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id); 00118 $this->DBFields = $DB->FetchRow(); 00119 00120 # copy file to storage 00121 $CopySucceeded = copy($IdOrFileName, $this->GetNameOfStoredFile()); 00122 00123 # if copy failed 00124 if (!$CopySucceeded) 00125 { 00126 # remove file info from database 00127 $DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id); 00128 00129 # set status indicating constructor failed 00130 $this->Status = self::FILESTAT_COPYERROR; 00131 } 00132 } 00133 } 00134 } 00135 else 00136 { 00137 # set status indicating constructor failed 00138 $this->Status = self::FILESTAT_PARAMERROR; 00139 } 00140 } 00141 00142 # return object status (used to report errors occurring in constructor) 00143 function Status() { return $this->Status; } 00144 00145 # get various attributes 00146 function Id() { return $this->Id; } 00147 function Name() { return $this->DBFields["FileName"]; } 00148 function GetLength() { return $this->DBFields["FileLength"]; } 00149 function GetType() { return $this->DBFields["FileType"]; } 00150 00151 # get/set various attributes 00152 function Comment($NewValue = DB_NOVALUE) 00153 { return $this->UpdateValue("FileComment", $NewValue); } 00154 function FieldId($NewValue = DB_NOVALUE) 00155 { return $this->UpdateValue("FieldId", $NewValue); } 00156 function ResourceId($NewValue = DB_NOVALUE) 00157 { return $this->UpdateValue("ResourceId", $NewValue); } 00158 00159 # get MIME type (defaults to "application/octet-stream" if not available) 00160 function GetMimeType() 00161 { 00162 return strlen($this->GetType()) 00163 ? $this->GetType() : "application/octet-stream"; 00164 } 00165 00166 # get link for downloading file 00167 function GetLink() 00168 { 00169 return "index.php?P=DownloadFile&Id=".$this->Id; 00170 } 00171 00172 # delete file (other methods are invalid after calling this!) 00173 function Delete() 00174 { 00175 # remove file entry from DB 00176 $this->DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id); 00177 00178 # delete file 00179 $FileName = $this->GetNameOfStoredFile(); 00180 if (file_exists($FileName)) 00181 { 00182 unlink($FileName); 00183 } 00184 } 00185 00186 # retrieve actual name of stored file 00187 function GetNameOfStoredFile() 00188 { 00189 return sprintf("FileStorage/%06d-%s-%s", 00190 $this->Id, $this->DBFields["SecretString"], $this->Name()); 00191 } 00192 00193 00194 # ---- PRIVATE INTERFACE ------------------------------------------------- 00195 00196 private $DB; 00197 private $Status; 00198 private $Id; 00199 private $DBFields; 00200 00201 # convenience function to supply parameters to Database->UpdateValue() 00202 private function UpdateValue($FieldName, $NewValue) 00203 { 00204 return $this->DB->UpdateValue("Files", $FieldName, $NewValue, 00205 "FileId = ".intval($this->Id), 00206 $this->DBFields, TRUE); 00207 } 00208 } 00209 00210 00211 ?>