3 * FusionForge file release system
5 * Copyright 2002, Tim Perdue/GForge, LLC
6 * Copyright 2009, Roland Mas
8 * This file is part of FusionForge.
10 * FusionForge is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published
12 * by the Free Software Foundation; either version 2 of the License,
13 * or (at your option) any later version.
15 * FusionForge is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with FusionForge; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 require_once $gfcommon.'include/Error.class.php';
28 class FRSFile extends Error {
31 * Associative array of data from db.
33 * @var array $data_array.
40 * @var object FRSRelease.
47 * @param object The FRSRelease object to which this file is associated.
48 * @param int The file_id.
49 * @param array The associative array of data.
50 * @return boolean success.
52 function FRSFile(&$FRSRelease, $file_id=false, $arr=false) {
54 if (!$FRSRelease || !is_object($FRSRelease)) {
55 $this->setError('FRSFile:: No Valid FRSRelease Object');
58 if ($FRSRelease->isError()) {
59 $this->setError('FRSFile:: '.$FRSRelease->getErrorMessage());
62 $this->FRSRelease =& $FRSRelease;
65 if (!$arr || !is_array($arr)) {
66 if (!$this->fetchData($file_id)) {
70 $this->data_array =& $arr;
71 if ($this->data_array['release_id'] != $this->FRSRelease->getID()) {
72 $this->setError('FRSRelease_id in db result does not match FRSRelease Object');
73 $this->data_array=null;
82 * create - create a new file in this FRSFileRelease/FRSPackage.
84 * @param string The name of this file.
85 * @param string The location of this file in the local file system.
86 * @param int The type_id of this file from the frs-file-types table.
87 * @param int The processor_id of this file from the frs-processor-types table.
88 * @param int The release_date of this file in unix time (seconds).
89 * @return boolean success.
91 function create($name,$file_location,$type_id,$processor_id,$release_time=false) {
92 if (strlen($name) < 3) {
93 $this->setError(_('FRSFile Name Must Be At Least 3 Characters'));
96 if (!util_is_valid_filename($name)) {
97 $this->setError(_('Filename can only be alphanumeric and "-" "_" "." characters.'));
101 // Can't really use is_uploaded_file() or move_uploaded_file()
102 // since we want this to be generalized code
103 // This is potentially exploitable if you do not validate
104 // before calling this function
106 if (!is_file($file_location) || !file_exists($file_location)) {
107 $this->setError(_('FRSFile Appears to be invalid'));
111 $perm =& $this->FRSRelease->FRSPackage->Group->getPermission( session_get_user() );
113 if (!$perm || !is_object($perm) || !$perm->isReleaseTechnician()) {
114 $this->setPermissionDeniedError();
119 // Filename must be unique in this release
121 $resfile = db_query_params ('SELECT filename FROM frs_file WHERE filename=$1 AND release_id=$2',
123 $this->FRSRelease->getId())) ;
124 if (!$resfile || db_numrows($resfile) > 0) {
125 $this->setError(_('That filename already exists in this project space').' '.db_error());
130 $path_name=forge_get_config('upload_dir').'/'.$this->FRSRelease->FRSPackage->Group->getUnixName();
131 if (!is_dir($path_name)) {
132 mkdir($path_name,0755);
134 if ( fileperms($path_name) != 0x4755 ) {
135 chmod($path_name,0755);
138 $path_name=$path_name.'/'.$this->FRSRelease->FRSPackage->getFileName();
139 if (!is_dir($path_name)) {
140 mkdir($path_name,0755);
142 if ( fileperms($path_name) != 0x4755 ) {
143 chmod($path_name,0755);
146 $path_name=$path_name.'/'.$this->FRSRelease->getFileName();
147 if (!is_dir($path_name)) {
148 mkdir($path_name,0755);
150 if ( fileperms($path_name) != 0x4755 ) {
151 chmod($path_name,0755);
155 $file_location=escapeshellcmd($file_location);
156 $newfilelocation = forge_get_config('upload_dir').'/'.
157 $this->FRSRelease->FRSPackage->Group->getUnixName().'/'.
158 $this->FRSRelease->FRSPackage->getFileName().'/'.
159 $this->FRSRelease->getFileName().'/';
161 rename($file_location, $newfilelocation.$name);
163 if (!file_exists($newfilelocation.$name)) {
164 $this->setError(_('File cannot be moved to the permanent location').': '.$newfilelocation.$name);
167 if (!$release_time) {
168 $release_time=time();
170 $file_size=filesize("$newfilelocation$name");
171 $sql="INSERT INTO frs_file(release_id,filename,release_time,
172 type_id,processor_id,file_size,post_date)
173 VALUES ('".$this->FRSRelease->getId()."','$name','$release_time',
174 '$type_id','$processor_id','$file_size','".time()."')";
177 $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)',
178 array ($this->FRSRelease->getId(),
187 $this->setError('FRSFile::create() Error Adding Release: '.db_error());
190 $this->file_id=db_insertid($result,'frs_file','file_id');
191 if (!$this->fetchData($this->file_id)) {
200 * fetchData - re-fetch the data for this FRSFile from the database.
202 * @param int The file_id.
203 * @return boolean success.
205 function fetchData($file_id) {
206 $res = db_query_params ('SELECT * FROM frs_file_vw WHERE file_id=$1 AND release_id=$2',
208 $this->FRSRelease->getID())) ;
209 if (!$res || db_numrows($res) < 1) {
210 $this->setError('FRSFile::fetchData() Invalid file_id');
213 $this->data_array =& db_fetch_array($res);
214 db_free_result($res);
219 * getFRSRelease - get the FRSRelease object this file is associated with.
221 * @return object The FRSRelease object.
223 function &getFRSRelease() {
224 return $this->FRSRelease;
228 * getID - get this file_id.
230 * @return int The id of this file.
233 return $this->data_array['file_id'];
237 * getName - get the name of this file.
239 * @return string The name of this file.
242 return $this->data_array['filename'];
246 * getSize - get the size of this file.
248 * @return int The size.
251 return $this->data_array['size'];
255 * getTypeID - the filetype id.
257 * @return int the filetype id.
259 function getTypeID() {
260 return $this->data_array['type_id'];
264 * getTypeName - the filetype name.
266 * @return string The filetype name.
268 function getFileType() {
269 return $this->data_array['filetype'];
273 * getProcessorID - the processor id.
275 * @return int the processor id.
277 function getProcessorID() {
278 return $this->data_array['processor_id'];
282 * getProcessor - the processor name.
284 * @return string The processor name.
286 function getProcessor() {
287 return $this->data_array['processor'];
291 * getDownloads - the number of downloads.
293 * @return int The number of downloads.
295 function getDownloads() {
296 return $this->data_array['downloads'];
300 * getReleaseTime - get the releasetime of this file.
302 * @return int The release time in unix time.
304 function getReleaseTime() {
305 return $this->data_array['release_time'];
309 * getPostDate - get the post time of this file.
311 * @return int The post time in unix time.
313 function getPostDate() {
314 return $this->data_array['post_time'];
318 * delete - Delete this file from the database and file system.
320 * @return boolean success.
323 $perm =& $this->FRSRelease->FRSPackage->Group->getPermission( session_get_user() );
325 if (!$perm || !is_object($perm) || !$perm->isReleaseTechnician()) {
326 $this->setPermissionDeniedError();
330 $file=forge_get_config('upload_dir').'/'.
331 $this->FRSRelease->FRSPackage->Group->getUnixName() . '/' .
332 $this->FRSRelease->FRSPackage->getFileName().'/'.
333 $this->FRSRelease->getFileName().'/'.
335 if (file_exists($file))
337 $result = db_query_params ('DELETE FROM frs_file WHERE file_id=$1',
338 array ($this->getID())) ;
339 if (!$result || db_affected_rows($result) < 1) {
340 $this->setError("frsDeleteFile()::2 ".db_error());
343 $res = db_query_params ('DELETE FROM frs_dlstats_file WHERE file_id=$1',
344 array ($this->getID())) ;
345 $res = db_query_params ('DELETE FROM frs_dlstats_filetotal_agg WHERE file_id=$1',
346 array ($this->getID())) ;
352 * update - update an existing file in this FRSFileRelease/FRSPackage.
354 * @param int The type_id of this file from the frs-file-types table.
355 * @param int The processor_id of this file from the frs-processor-types table.
356 * @param int The release_date of this file in unix time (seconds).
357 * @param int The release_id of the release this file belongs to (if not set, defaults to the release id of this file).
358 * @return boolean success.
360 function update($type_id,$processor_id,$release_time,$release_id=false) {
361 $perm =& $this->FRSRelease->FRSPackage->Group->getPermission( session_get_user() );
363 if (!$perm || !is_object($perm) || !$perm->isReleaseTechnician()) {
364 $this->setPermissionDeniedError();
370 // Check that the new FRSRelease id exists
371 if ($FRSRelease=frsrelease_get_object($release_id)) {
372 // Check that the new FRSRelease id belongs to the group of this FRSFile
373 if ($FRSRelease->FRSPackage->Group->getID()!=$this->FRSRelease->FRSPackage->Group->getID()) {
374 $this->setError('FRSFile:: No Valid Group Object');
378 $this->setError('FRSFile:: No Valid FRSRelease Object');
382 // If release_id is not set, defaults to the release id of this file
383 $release_id = $this->FRSRelease->getID();
388 $res = db_query_params ('UPDATE frs_file SET type_id=$1,processor_id=$2,release_time=$3,release_id=$4 WHERE file_id=$5',
395 if (!$res || db_affected_rows($res) < 1) {
396 $this->setError('FRSFile::update() Error On Update: '.db_error());
400 // Move physically file if needed
401 if ($release_id != $this->FRSRelease->getID()) {
402 $old_file_location = forge_get_config('upload_dir').'/'.
403 $this->FRSRelease->FRSPackage->Group->getUnixName().'/'.
404 $this->FRSRelease->FRSPackage->getFileName().'/'.
405 $this->FRSRelease->getFileName().'/'.
406 $this->data_array['filename'];
407 $new_file_location = forge_get_config('upload_dir').'/'.
408 $FRSRelease->FRSPackage->Group->getUnixName().'/'.
409 $FRSRelease->FRSPackage->getFileName().'/'.
410 $FRSRelease->getFileName().'/'.
411 $this->data_array['filename'];
412 if (file_exists($new_file_location)) {
414 $this->setError(_('That filename already exists in this project space'));
417 $cmd="/bin/mv $old_file_location $new_file_location";
419 if (!file_exists($new_file_location)) {
421 $this->setError(_('File cannot be moved to the permanent location').': '.$new_file_location);
432 // c-file-style: "bsd"