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 ?>