5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2010-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
15 # ---- PUBLIC INTERFACE --------------------------------------------------
17 # status codes (set by constructor and returned by File::Status())
38 function File($IdOrFileName, $ResourceId = NULL, $FieldId = NULL,
39 $DesiredFileName = NULL, $CheckFileLength = TRUE)
41 # assume constructor will succeed
42 $this->
Status = self::FILESTAT_OK;
44 # get our own database handle
49 if (is_numeric($IdOrFileName))
51 # set file ID from supplied value
52 $this->
Id = intval($IdOrFileName);
54 # load file info from database
55 $DB->Query(
"SELECT * FROM Files WHERE FileId = ".$this->
Id);
56 $this->DBFields = $DB->FetchRow();
58 # if the image wasn't found in the database
59 if (!$DB->NumRowsSelected())
61 $this->
Status = self::FILESTAT_DOESNOTEXIST;
64 # else if file name and resource ID and field ID supplied
65 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
67 # if file does not exist
68 $TempFileName = $IdOrFileName;
69 if (!file_exists($TempFileName) || !is_readable($TempFileName))
71 # set status indicating appropriate error
72 $this->
Status = file_exists($TempFileName)
73 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
77 # if we were asked to check file length and file was zero length
78 $FileLength = filesize($TempFileName);
79 if ($CheckFileLength && !$FileLength)
81 # set status indicating zero length file
82 $this->
Status = self::FILESTAT_ZEROLENGTH;
86 # generate secret string (used to protect from unauthorized download)
87 srand((
double)microtime() * 1000000);
88 $SecretString = sprintf(
"%04X", rand(1, 30000));
90 # attempt to get file type
92 if (function_exists(
"finfo_open"))
94 $FInfoHandle = finfo_open(FILEINFO_MIME);
98 $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
99 finfo_close($FInfoHandle);
103 $FileType = $FInfoMime;
107 else if (function_exists(
"mime_content_type"))
109 # mime_content_type has been deprecated, but it may be
110 # the only way to get the mimetype for PHP < 5.3
111 $MimeType = mime_content_type($TempFileName);
115 $FileType = $MimeType;
119 # add file info to database
120 $BaseFileName = $DesiredFileName
121 ? basename($DesiredFileName) : basename($TempFileName);
122 $DB->Query(
"INSERT INTO Files"
123 .
" (ResourceId, FieldId, FileName, FileLength, FileType,"
126 .intval($ResourceId).
", "
127 .intval($FieldId).
", "
128 .
"'".addslashes($BaseFileName).
"', "
131 .
"'".$SecretString.
"')");
133 # retrieve ID of new file
134 $this->
Id = $DB->LastInsertId();
136 # load file info back in from database
137 $DB->Query(
"SELECT * FROM Files WHERE FileId = ".$this->
Id);
138 $this->DBFields = $DB->FetchRow();
140 # copy file to storage
146 # remove file info from database
147 $DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
149 # set status indicating constructor failed
150 $this->
Status = self::FILESTAT_COPYERROR;
157 # set status indicating constructor failed
158 $this->
Status = self::FILESTAT_PARAMERROR;
166 function Status() {
return $this->Status; }
172 function Id() {
return $this->Id; }
178 function Name() {
return $this->DBFields[
"FileName"]; }
184 function GetLength() {
return $this->DBFields[
"FileLength"]; }
190 function GetType() {
return $this->DBFields[
"FileType"]; }
198 {
return $this->UpdateValue(
"FileComment", $NewValue); }
206 {
return $this->UpdateValue(
"FieldId", $NewValue); }
214 {
return $this->UpdateValue(
"ResourceId", $NewValue); }
222 return strlen($this->
GetType())
223 ? $this->
GetType() :
"application/octet-stream";
235 # if CleanURLs are enabled, use the redirect that includes
236 # the file name so that browsers don't use index.php as the name
237 # for the downloaded file
238 if ($GLOBALS[
"G_PluginManager"]->PluginEnabled(
"CleanURLs"))
240 return "downloads/".$this->Id.
"/".rawurlencode($this->
Name());
243 # otherwise use the download portal
246 return "index.php?P=DownloadFile&Id=".$this->Id;
256 # remove file entry from DB
257 $this->DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
261 if (file_exists($FileName))
273 # for each possible storage location
274 foreach (self::$StorageLocations as $Dir)
276 # build file name for that location
277 $FileName = sprintf($Dir.
"/%06d-%s-%s",
278 $this->Id, $this->DBFields[
"SecretString"], $this->Name());
280 # if file can be found in that location
281 if (file_exists($FileName))
283 # return file name to caller
288 # build file name for default (most preferred) location
289 $FileName = sprintf(self::GetStorageDirectory().
"/%06d-%s-%s",
290 $this->
Id, $this->DBFields[
"SecretString"], $this->
Name());
292 # return file name to caller
302 # for each possible storage location
303 foreach (self::$StorageLocations as $Dir)
305 # if location exists and is writeable
306 if (is_dir($Dir) && is_writeable($Dir))
308 # return location to caller
313 # return default (most preferred) location to caller
314 return self::$StorageLocations[0];
318 # ---- PRIVATE INTERFACE -------------------------------------------------
326 static private $StorageLocations = array(
337 private function UpdateValue($FieldName, $NewValue)
339 return $this->DB->UpdateValue(
"Files", $FieldName, $NewValue,
340 "FileId = ".intval($this->
Id),
341 $this->DBFields, TRUE);
const FILESTAT_ZEROLENGTH
GetNameOfStoredFile()
Returns the relative link to the stored file.
const FILESTAT_UNREADABLE
GetType()
Gets the file's type.
const FILESTAT_DOESNOTEXIST
SQL database abstraction object with smart query caching.
FieldId($NewValue=DB_NOVALUE)
Gets or sets the field ID of the File.
Id()
Gets the object's ID.
GetLink()
Returns the relative download link to download the file.
const FILESTAT_PARAMERROR
Delete()
Deletes the file and removes its entry from the database.
Status()
Gets the object's status.
GetMimeType()
Gets the MIME type of the file.
GetLength()
Gets the length of the file.
static GetStorageDirectory()
Get file storage directory.
ResourceId($NewValue=DB_NOVALUE)
Gets or sets the resource ID of the File.
Name()
Gets the name of the object.
Class representing a stored (usually uploaded) file.
Comment($NewValue=DB_NOVALUE)
Gets or sets the comment on the file.
File($IdOrFileName, $ResourceId=NULL, $FieldId=NULL, $DesiredFileName=NULL, $CheckFileLength=TRUE)
Constructs a File object using either an existing file or a new file.