3 * FusionForge file release system
5 * Copyright 2002, Tim Perdue/GForge, LLC
6 * Copyright 2009, Roland Mas
8 * This file is part of FusionForge. FusionForge is free software;
9 * you can redistribute it and/or modify it under the terms of the
10 * GNU General Public License as published by the Free Software
11 * Foundation; either version 2 of the Licence, or (at your option)
14 * FusionForge is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 require_once $gfcommon.'include/Error.class.php';
27 * Factory method which creates a FRSFile from an release id
29 * @param int The file id
30 * @param array The result array, if it's passed in
31 * @return object FRSFile object
33 function &frsfile_get_object($file_id, $data=false) {
35 if (!isset($FRSFILE_OBJ['_'.$file_id.'_'])) {
37 //the db result handle was passed in
39 $res = db_query_params ('SELECT * FROM frs_file WHERE file_id=$1',
41 if (db_numrows($res)<1 ) {
42 $FRSFILE_OBJ['_'.$file_id.'_']=false;
45 $data = db_fetch_array($res);
47 $FRSRelease =& frsrelease_get_object($data['release_id']);
48 $FRSFILE_OBJ['_'.$file_id.'_']= new FRSFile($FRSRelease,$data['file_id'],$data);
50 return $FRSFILE_OBJ['_'.$file_id.'_'];
53 class FRSFile extends Error {
56 * Associative array of data from db.
58 * @var array $data_array.
65 * @var object FRSRelease.
72 * @param object The FRSRelease object to which this file is associated.
73 * @param int The file_id.
74 * @param array The associative array of data.
75 * @return boolean success.
77 function FRSFile(&$FRSRelease, $file_id=false, $arr=false) {
79 if (!$FRSRelease || !is_object($FRSRelease)) {
80 $this->setError('FRSFile:: No Valid FRSRelease Object');
83 if ($FRSRelease->isError()) {
84 $this->setError('FRSFile:: '.$FRSRelease->getErrorMessage());
87 $this->FRSRelease =& $FRSRelease;
90 if (!$arr || !is_array($arr)) {
91 if (!$this->fetchData($file_id)) {
95 $this->data_array =& $arr;
96 if ($this->data_array['release_id'] != $this->FRSRelease->getID()) {
97 $this->setError('FRSRelease_id in db result does not match FRSRelease Object');
98 $this->data_array=null;
107 * create - create a new file in this FRSFileRelease/FRSPackage.
109 * @param string The name of this file.
110 * @param string The location of this file in the local file system.
111 * @param int The type_id of this file from the frs-file-types table.
112 * @param int The processor_id of this file from the frs-processor-types table.
113 * @param int The release_date of this file in unix time (seconds).
114 * @return boolean success.
116 function create($name,$file_location,$type_id,$processor_id,$release_time=false) {
117 if (strlen($name) < 3) {
118 $this->setError(_('FRSFile Name Must Be At Least 3 Characters'));
121 if (!util_is_valid_filename($name)) {
122 $this->setError(_('Filename can only be alphanumeric and "-" "_" "+" "." "~" characters.'));
126 // Can't really use is_uploaded_file() or move_uploaded_file()
127 // since we want this to be generalized code
128 // This is potentially exploitable if you do not validate
129 // before calling this function
131 if (!is_file($file_location) || !file_exists($file_location)) {
132 $this->setError(_('FRSFile Appears to be invalid'));
136 if (!forge_check_perm ('frs', $this->FRSRelease->FRSPackage->Group->getID(), 'write')) {
137 $this->setPermissionDeniedError();
142 // Filename must be unique in this release
144 $resfile = db_query_params ('SELECT filename FROM frs_file WHERE filename=$1 AND release_id=$2',
146 $this->FRSRelease->getId())) ;
147 if (!$resfile || db_numrows($resfile) > 0) {
148 $this->setError(_('That filename already exists in this project space').' '.db_error());
153 $path_name=forge_get_config('upload_dir').'/'.$this->FRSRelease->FRSPackage->Group->getUnixName();
154 if (!is_dir($path_name)) {
155 mkdir($path_name,0755);
157 if ( fileperms($path_name) != 0x4755 ) {
158 chmod($path_name,0755);
161 $path_name=$path_name.'/'.$this->FRSRelease->FRSPackage->getFileName();
162 if (!is_dir($path_name)) {
163 mkdir($path_name,0755);
165 if ( fileperms($path_name) != 0x4755 ) {
166 chmod($path_name,0755);
169 $path_name=$path_name.'/'.$this->FRSRelease->getFileName();
170 if (!is_dir($path_name)) {
171 mkdir($path_name,0755);
173 if ( fileperms($path_name) != 0x4755 ) {
174 chmod($path_name,0755);
178 $newfilelocation = forge_get_config('upload_dir').'/'.
179 $this->FRSRelease->FRSPackage->Group->getUnixName().'/'.
180 $this->FRSRelease->FRSPackage->getFileName().'/'.
181 $this->FRSRelease->getFileName().'/';
183 $ret = rename($file_location, $newfilelocation.$name);
185 $this->setError(_('File cannot be moved to the permanent location').': '.$newfilelocation.$name);
189 if (!$release_time) {
190 $release_time=time();
192 $file_size=filesize("$newfilelocation$name");
193 $sql="INSERT INTO frs_file(release_id,filename,release_time,
194 type_id,processor_id,file_size,post_date)
195 VALUES ('".$this->FRSRelease->getId()."','$name','$release_time',
196 '$type_id','$processor_id','$file_size','".time()."')";
199 $result = db_query_params ('INSERT INTO frs_file(release_id,filename,release_time,type_id,processor_id,file_size,post_date) VALUES ($1,$2,$3,$4,$5,$6,$7)',
200 array ($this->FRSRelease->getId(),
208 $this->setError('FRSFile::create() Error Adding Release: '.db_error());
212 $this->file_id=db_insertid($result,'frs_file','file_id');
213 if (!$this->fetchData($this->file_id)) {
218 $this->FRSRelease->FRSPackage->createNewestReleaseFilesAsZip();
224 * fetchData - re-fetch the data for this FRSFile from the database.
226 * @param int The file_id.
227 * @return boolean success.
229 function fetchData($file_id) {
230 $res = db_query_params ('SELECT * FROM frs_file_vw WHERE file_id=$1 AND release_id=$2',
232 $this->FRSRelease->getID())) ;
233 if (!$res || db_numrows($res) < 1) {
234 $this->setError('FRSFile::fetchData() Invalid file_id');
237 $this->data_array = db_fetch_array($res);
238 db_free_result($res);
243 * getFRSRelease - get the FRSRelease object this file is associated with.
245 * @return object The FRSRelease object.
247 function &getFRSRelease() {
248 return $this->FRSRelease;
252 * getID - get this file_id.
254 * @return int The id of this file.
257 return $this->data_array['file_id'];
261 * getName - get the name of this file.
263 * @return string The name of this file.
266 return $this->data_array['filename'];
270 * getSize - get the size of this file.
272 * @return int The size.
275 return $this->data_array['file_size'];
279 * getTypeID - the filetype id.
281 * @return int the filetype id.
283 function getTypeID() {
284 return $this->data_array['type_id'];
288 * getTypeName - the filetype name.
290 * @return string The filetype name.
292 function getFileType() {
293 return $this->data_array['filetype'];
297 * getProcessorID - the processor id.
299 * @return int the processor id.
301 function getProcessorID() {
302 return $this->data_array['processor_id'];
306 * getProcessor - the processor name.
308 * @return string The processor name.
310 function getProcessor() {
311 return $this->data_array['processor'];
315 * getDownloads - the number of downloads.
317 * @return int The number of downloads.
319 function getDownloads() {
320 return $this->data_array['downloads'];
324 * getReleaseTime - get the releasetime of this file.
326 * @return int The release time in unix time.
328 function getReleaseTime() {
329 return $this->data_array['release_time'];
333 * getPostDate - get the post date of this file.
335 * @return int The post date in unix time.
337 function getPostDate() {
338 return $this->data_array['post_date'];
342 * delete - Delete this file from the database and file system.
344 * @return boolean success.
347 if (!forge_check_perm ('frs', $this->FRSRelease->FRSPackage->Group->getID(), 'write')) {
348 $this->setPermissionDeniedError();
352 $file=forge_get_config('upload_dir').'/'.
353 $this->FRSRelease->FRSPackage->Group->getUnixName() . '/' .
354 $this->FRSRelease->FRSPackage->getFileName().'/'.
355 $this->FRSRelease->getFileName().'/'.
357 if (file_exists($file))
359 $result = db_query_params ('DELETE FROM frs_file WHERE file_id=$1',
360 array ($this->getID())) ;
361 if (!$result || db_affected_rows($result) < 1) {
362 $this->setError("frsDeleteFile()::2 ".db_error());
365 $res = db_query_params ('DELETE FROM frs_dlstats_file WHERE file_id=$1',
366 array ($this->getID())) ;
367 $res = db_query_params ('DELETE FROM frs_dlstats_filetotal_agg WHERE file_id=$1',
368 array ($this->getID())) ;
369 $this->FRSRelease->FRSPackage->createNewestReleaseFilesAsZip();
375 * update - update an existing file in this FRSFileRelease/FRSPackage.
377 * @param int The type_id of this file from the frs-file-types table.
378 * @param int The processor_id of this file from the frs-processor-types table.
379 * @param int The release_date of this file in unix time (seconds).
380 * @param int The release_id of the release this file belongs to (if not set, defaults to the release id of this file).
381 * @return boolean success.
383 function update($type_id,$processor_id,$release_time,$release_id=false) {
384 if (!forge_check_perm ('frs', $this->FRSRelease->FRSPackage->Group->getID(), 'write')) {
385 $this->setPermissionDeniedError();
391 // Check that the new FRSRelease id exists
392 if ($FRSRelease=frsrelease_get_object($release_id)) {
393 // Check that the new FRSRelease id belongs to the group of this FRSFile
394 if ($FRSRelease->FRSPackage->Group->getID()!=$this->FRSRelease->FRSPackage->Group->getID()) {
395 $this->setError('FRSFile:: No Valid Group Object');
399 $this->setError('FRSFile:: No Valid FRSRelease Object');
403 // If release_id is not set, defaults to the release id of this file
404 $release_id = $this->FRSRelease->getID();
409 $res = db_query_params ('UPDATE frs_file SET type_id=$1,processor_id=$2,release_time=$3,release_id=$4 WHERE file_id=$5',
416 if (!$res || db_affected_rows($res) < 1) {
417 $this->setError('FRSFile::update() Error On Update: '.db_error());
422 // Move physically file if needed
423 if ($release_id != $this->FRSRelease->getID()) {
424 $old_file_location = forge_get_config('upload_dir').'/'.
425 $this->FRSRelease->FRSPackage->Group->getUnixName().'/'.
426 $this->FRSRelease->FRSPackage->getFileName().'/'.
427 $this->FRSRelease->getFileName().'/'.
428 $this->data_array['filename'];
429 $new_file_location = forge_get_config('upload_dir').'/'.
430 $FRSRelease->FRSPackage->Group->getUnixName().'/'.
431 $FRSRelease->FRSPackage->getFileName().'/'.
432 $FRSRelease->getFileName().'/'.
433 $this->data_array['filename'];
434 if (file_exists($new_file_location)) {
435 $this->setError(_('That filename already exists in this project space'));
439 $ret = rename($old_file_location, $new_file_location);
441 $this->setError(_('File cannot be moved to the permanent location').': '.$new_file_location);
447 $this->FRSRelease->FRSPackage->createNewestReleaseFilesAsZip();
454 // c-file-style: "bsd"