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