CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

File.php
Go to the documentation of this file.
1 <?PHP
2
3 #
4 # FILE: File.php
5 #
6 # Copyright 2010 Edward Almasy and Internet Scout
7 # http://scout.wisc.edu
8 #
9
10
11 class File {
12
13 # ---- PUBLIC INTERFACE --------------------------------------------------
14
15 # status codes (set by constructor and returned by File::Status())
16 const FILESTAT_OK = 0;
17 const FILESTAT_COPYERROR = 1;
18 const FILESTAT_PARAMERROR = 2;
19 const FILESTAT_ZEROLENGTH = 3;
20 const FILESTAT_DOESNOTEXIST = 4;
21 const FILESTAT_UNREADABLE = 5;
22
23 # object constructor
24 function File($IdOrFileName, $ResourceId = NULL, $FieldId = NULL,
25 $DesiredFileName = NULL, $CheckFileLength = TRUE)
26 {
27 # assume constructor will succeed
28 $this->Status = self::FILESTAT_OK;
29
30 # get our own database handle
31 $DB = new Database();
32 $this->DB = $DB;
33
34 # if ID supplied
35 if (is_int($IdOrFileName))
36 {
37 # set file ID from supplied value
38 $this->Id = intval($IdOrFileName);
39
40 # load file info from database
41 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
42 $this->DBFields = $DB->FetchRow();
43
44 # if the image wasn't found in the database
45 if (!$DB->NumRowsSelected())
46 {
47 $this->Status = self::FILESTAT_DOESNOTEXIST;
48 }
49 }
50 # else if file name and resource ID and field ID supplied
51 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
52 {
53 # if file does not exist
54 $TempFileName = $IdOrFileName;
55 if (!file_exists($TempFileName) || !is_readable($TempFileName))
56 {
57 # set status indicating appropriate error
58 $this->Status = file_exists($TempFileName)
59 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
60 }
61 else
62 {
63 # if we were asked to check file length and file was zero length
64 $FileLength = filesize($TempFileName);
65 if ($CheckFileLength && !$FileLength)
66 {
67 # set status indicating zero length file
68 $this->Status = self::FILESTAT_ZEROLENGTH;
69 }
70 else
71 {
72 # generate secret string (used to protect from unauthorized download)
73 srand((double)microtime() * 1000000);
74 $SecretString = sprintf("%04X", rand(1, 30000));
75
76 # attempt to get file type
77 $FileType = "";
78 if (function_exists("finfo_open"))
79 {
80 $FInfoHandle = finfo_open(FILEINFO_MIME);
81
82 if ($FInfoHandle)
83 {
84 $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
85 finfo_close($FInfoHandle);
86
87 if ($FInfoMime)
88 {
89 $FileType = $FInfoMime;
90 }
91 }
92 }
93 else if (function_exists("mime_content_type"))
94 {
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);
98
99 if ($MimeType)
100 {
101 $FileType = $MimeType;
102 }
103 }
104
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,"
110 ." SecretString)"
111 ." VALUES ("
112 .intval($ResourceId).", "
113 .intval($FieldId).", "
114 ."'".addslashes($BaseFileName)."', "
115 .$FileLength.", "
116 ."'".$FileType."', "
117 ."'".$SecretString."')");
118
119 # retrieve ID of new file
120 $this->Id = $DB->LastInsertId("Files");
121
122 # load file info back in from database
123 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
124 $this->DBFields = $DB->FetchRow();
125
126 # copy file to storage
127 $CopySucceeded = copy($IdOrFileName, $this->GetNameOfStoredFile());
128
129 # if copy failed
130 if (!$CopySucceeded)
131 {
132 # remove file info from database
133 $DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
134
135 # set status indicating constructor failed
136 $this->Status = self::FILESTAT_COPYERROR;
137 }
138 }
139 }
140 }
141 else
142 {
143 # set status indicating constructor failed
144 $this->Status = self::FILESTAT_PARAMERROR;
145 }
146 }
147
148 # return object status (used to report errors occurring in constructor)
149 function Status() { return $this->Status; }
150
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"]; }
156
157 # get/set various attributes
158 function Comment($NewValue = DB_NOVALUE)
159 { return $this->UpdateValue("FileComment", $NewValue); }
160 function FieldId($NewValue = DB_NOVALUE)
161 { return $this->UpdateValue("FieldId", $NewValue); }
162 function ResourceId($NewValue = DB_NOVALUE)
163 { return $this->UpdateValue("ResourceId", $NewValue); }
164
165 # get MIME type (defaults to "application/octet-stream" if not available)
166 function GetMimeType()
167 {
168 return strlen($this->GetType())
169 ? $this->GetType() : "application/octet-stream";
170 }
171
172 # get link for downloading file
173 function GetLink()
174 {
175 global $AF;
176
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())
181 {
182 return "downloads/".$this->Id."/".rawurlencode($this->Name());
183 }
184
185 # otherwise use the download portal
186 else
187 {
188 return "index.php?P=DownloadFile&Id=".$this->Id;
189 }
190 }
191
192 # delete file (other methods are invalid after calling this!)
193 function Delete()
194 {
195 # remove file entry from DB
196 $this->DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
197
198 # delete file
199 $FileName = $this->GetNameOfStoredFile();
200 if (file_exists($FileName))
201 {
202 unlink($FileName);
203 }
204 }
205
206 # retrieve actual name of stored file
207 function GetNameOfStoredFile()
208 {
209 return sprintf("FileStorage/%06d-%s-%s",
210 $this->Id, $this->DBFields["SecretString"], $this->Name());
211 }
212
213
214 # ---- PRIVATE INTERFACE -------------------------------------------------
215
216 private $DB;
217 private $Status;
218 private $Id;
219 private $DBFields;
220
221 # convenience function to supply parameters to Database->UpdateValue()
222 private function UpdateValue($FieldName, $NewValue)
223 {
224 return $this->DB->UpdateValue("Files", $FieldName, $NewValue,
225 "FileId = ".intval($this->Id),
226 $this->DBFields, TRUE);
227 }
228 }
229
230
231 ?>