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 # else if file name and resource ID and field ID supplied
45 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
47 # if file does not exist
48 $TempFileName = $IdOrFileName;
49 if (!file_exists($TempFileName) || !is_readable($TempFileName))
51 # set status indicating appropriate error
52 $this->
Status = file_exists($TempFileName)
53 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
57 # if we were asked to check file length and file was zero length
58 $FileLength = filesize($TempFileName);
59 if ($CheckFileLength && !$FileLength)
61 # set status indicating zero length file
62 $this->
Status = self::FILESTAT_ZEROLENGTH;
66 # generate secret string (used to protect from unauthorized download)
67 srand((
double)microtime() * 1000000);
68 $SecretString = sprintf(
"%04X", rand(1, 30000));
70 # attempt to get file type
72 if (function_exists(
"finfo_open"))
74 $FInfoHandle = finfo_open(FILEINFO_MIME);
78 $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
79 finfo_close($FInfoHandle);
83 $FileType = $FInfoMime;
87 else if (function_exists(
"mime_content_type"))
89 # mime_content_type has been deprecated, but it may be
90 # the only way to get the mimetype for PHP < 5.3
91 $MimeType = mime_content_type($TempFileName);
95 $FileType = $MimeType;
99 # add file info to database
100 $BaseFileName = $DesiredFileName
101 ? basename($DesiredFileName) : basename($TempFileName);
102 $DB->Query(
"INSERT INTO Files"
103 .
" (ResourceId, FieldId, FileName, FileLength, FileType,"
106 .intval($ResourceId).
", "
107 .intval($FieldId).
", "
108 .
"'".addslashes($BaseFileName).
"', "
111 .
"'".$SecretString.
"')");
113 # retrieve ID of new file
114 $this->
Id = $DB->LastInsertId(
"Files");
116 # load file info back in from database
117 $DB->Query(
"SELECT * FROM Files WHERE FileId = ".$this->
Id);
118 $this->DBFields = $DB->FetchRow();
120 # copy file to storage
126 # remove file info from database
127 $DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
129 # set status indicating constructor failed
130 $this->
Status = self::FILESTAT_COPYERROR;
137 # set status indicating constructor failed
138 $this->
Status = self::FILESTAT_PARAMERROR;
142 # return object status (used to report errors occurring in constructor)
143 function Status() {
return $this->Status; }
145 # get various attributes
146 function Id() {
return $this->Id; }
147 function Name() {
return $this->DBFields[
"FileName"]; }
148 function GetLength() {
return $this->DBFields[
"FileLength"]; }
149 function GetType() {
return $this->DBFields[
"FileType"]; }
151 # get/set various attributes
153 {
return $this->UpdateValue(
"FileComment", $NewValue); }
155 {
return $this->UpdateValue(
"FieldId", $NewValue); }
157 {
return $this->UpdateValue(
"ResourceId", $NewValue); }
159 # get MIME type (defaults to "application/octet-stream" if not available)
162 return strlen($this->
GetType())
163 ? $this->
GetType() :
"application/octet-stream";
166 # get link for downloading file
171 # if .htaccess files are supported, use the redirect that includes
172 # the file name so that browsers don't use index.php as the name
173 # for the downloaded file
174 if ($AF->HtaccessSupport())
176 return "downloads/".$this->Id.
"/".rawurlencode($this->
Name());
179 # otherwise use the download portal
182 return "index.php?P=DownloadFile&Id=".$this->Id;
186 # delete file (other methods are invalid after calling this!)
189 # remove file entry from DB
190 $this->DB->Query(
"DELETE FROM Files WHERE FileId = ".$this->
Id);
194 if (file_exists($FileName))
200 # retrieve actual name of stored file
203 return sprintf(
"FileStorage/%06d-%s-%s",
204 $this->
Id, $this->DBFields[
"SecretString"], $this->
Name());
208 # ---- PRIVATE INTERFACE -------------------------------------------------
215 # convenience function to supply parameters to Database->UpdateValue()
216 private function UpdateValue($FieldName, $NewValue)
218 return $this->DB->UpdateValue(
"Files", $FieldName, $NewValue,
219 "FileId = ".intval($this->
Id),
220 $this->DBFields, TRUE);