6 # Copyright 2010 Edward Almasy and Internet Scout
7 # http://scout.wisc.edu
13 # ---- PUBLIC INTERFACE --------------------------------------------------
15 # status codes (set by constructor and returned by File::Status())
24 function File($IdOrFileName, $ResourceId = NULL, $FieldId = NULL,
25 $DesiredFileName = NULL, $CheckFileLength = TRUE)
27 # assume constructor will succeed
28 $this->
Status = self::FILESTAT_OK;
30 # get our own database handle
35 if (is_int($IdOrFileName))
37 # set file ID from supplied value
38 $this->
Id = intval($IdOrFileName);
40 # load file info from database
41 $DB->Query(
"SELECT * FROM Files WHERE FileId = ".$this->
Id);
42 $this->DBFields = $DB->FetchRow();
44 # if the image wasn't found in the database
45 if (!$DB->NumRowsSelected())
47 $this->
Status = self::FILESTAT_DOESNOTEXIST;
50 # else if file name and resource ID and field ID supplied
51 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
53 # if file does not exist
54 $TempFileName = $IdOrFileName;
55 if (!file_exists($TempFileName) || !is_readable($TempFileName))
57 # set status indicating appropriate error
58 $this->
Status = file_exists($TempFileName)
59 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
63 # if we were asked to check file length and file was zero length
64 $FileLength = filesize($TempFileName);
65 if ($CheckFileLength && !$FileLength)
67 # set status indicating zero length file
68 $this->
Status = self::FILESTAT_ZEROLENGTH;
72 # generate secret string (used to protect from unauthorized download)
73 srand((
double)microtime() * 1000000);
74 $SecretString = sprintf(
"%04X", rand(1, 30000));
76 # attempt to get file type
78 if (function_exists(
"finfo_open"))
80 $FInfoHandle = finfo_open(FILEINFO_MIME);
84 $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
85 finfo_close($FInfoHandle);
89 $FileType = $FInfoMime;
93 else if (function_exists(
"mime_content_type"))
95 # mime_content_type has been deprecated, but it may be
96 # the only way to get the mimetype for PHP < 5.3
97 $MimeType = mime_content_type($TempFileName);
101 $FileType = $MimeType;
105 # add file info to database
106 $BaseFileName = $DesiredFileName
107 ? basename($DesiredFileName) : basename($TempFileName);
108 $DB->Query(
"INSERT INTO Files"
109 .
" (ResourceId, FieldId, FileName, FileLength, FileType,"
112 .intval($ResourceId).
", "
113 .intval($FieldId).
", "
114 .
"'".addslashes($BaseFileName).
"', "
117 .
"'".$SecretString.
"')");
119 # retrieve ID of new file
120 $this->
Id = $DB->LastInsertId(
"Files");
122 # load file info back in from database
123 $DB->Query(
"SELECT * FROM Files WHERE FileId = ".$this->
Id);
124 $this->DBFields = $DB->FetchRow();
126 # copy file to storage
132 # remove file info from database
133 $DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
135 # set status indicating constructor failed
136 $this->
Status = self::FILESTAT_COPYERROR;
143 # set status indicating constructor failed
144 $this->
Status = self::FILESTAT_PARAMERROR;
148 # return object status (used to report errors occurring in constructor)
149 function Status() {
return $this->Status; }
151 # get various attributes
152 function Id() {
return $this->Id; }
153 function Name() {
return $this->DBFields[
"FileName"]; }
154 function GetLength() {
return $this->DBFields[
"FileLength"]; }
155 function GetType() {
return $this->DBFields[
"FileType"]; }
157 # get/set various attributes
159 {
return $this->UpdateValue(
"FileComment", $NewValue); }
161 {
return $this->UpdateValue(
"FieldId", $NewValue); }
163 {
return $this->UpdateValue(
"ResourceId", $NewValue); }
165 # get MIME type (defaults to "application/octet-stream" if not available)
168 return strlen($this->
GetType())
169 ? $this->
GetType() :
"application/octet-stream";
172 # get link for downloading file
177 # if .htaccess files are supported, use the redirect that includes
178 # the file name so that browsers don't use index.php as the name
179 # for the downloaded file
180 if ($AF->HtaccessSupport())
182 return "downloads/".$this->Id.
"/".rawurlencode($this->
Name());
185 # otherwise use the download portal
188 return "index.php?P=DownloadFile&Id=".$this->Id;
192 # delete file (other methods are invalid after calling this!)
195 # remove file entry from DB
196 $this->DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
200 if (file_exists($FileName))
206 # retrieve actual name of stored file
209 return sprintf(
"FileStorage/%06d-%s-%s",
210 $this->
Id, $this->DBFields[
"SecretString"], $this->
Name());
214 # ---- PRIVATE INTERFACE -------------------------------------------------
221 # convenience function to supply parameters to Database->UpdateValue()
222 private function UpdateValue($FieldName, $NewValue)
224 return $this->DB->UpdateValue(
"Files", $FieldName, $NewValue,
225 "FileId = ".intval($this->
Id),
226 $this->DBFields, TRUE);