]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/upload_file.php
Release 6.1.4
[Github/sugarcrm.git] / include / upload_file.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * Description:
41  ********************************************************************************/
42
43 class UploadFile 
44 {
45         var $field_name;
46         var $stored_file_name;
47         var $original_file_name;
48         var $temp_file_location;
49         var $use_soap = false;
50         var $file;
51         var $file_ext;
52         
53         function UploadFile ($field_name) {
54                 // $field_name is the name of your passed file selector field in your form
55                 // i.e., for Emails, it is "email_attachmentX" where X is 0-9
56                 $this->field_name = $field_name;
57         // Bug 28408 -  Add automatic creation of upload cache directory if it doesn't exist
58                 if ( !is_dir($GLOBALS['sugar_config']['upload_dir']) ) 
59             create_cache_directory(str_replace($GLOBALS['sugar_config']['cache_dir'],'',$GLOBALS['sugar_config']['upload_dir']));
60         }
61
62         function set_for_soap($filename, $file) {
63                 $this->stored_file_name = $filename;
64                 $this->use_soap = true;
65                 $this->file = $file;
66         }
67
68         /**
69          * wrapper for this::get_file_path()
70          * @param string stored_file_name File name in filesystem
71          * @param string bean_id note bean ID
72          * @return string path with file name
73          */
74         function get_url($stored_file_name,$bean_id) {
75                 global $sugar_config;
76                 return UploadFile::get_file_path($stored_file_name,$bean_id);
77         }
78         
79         /**
80          * builds a URL path for an anchor tag 
81          * @param string stored_file_name File name in filesystem
82          * @param string bean_id note bean ID
83          * @return string path with file name
84          */
85         function get_file_path($stored_file_name,$bean_id) {
86                 global $sugar_config;
87                 global $locale;
88         
89         // if the parameters are empty strings, just return back the upload_dir
90                 if ( empty($bean_id) && empty($stored_file_name) )
91             return $sugar_config['upload_dir'];
92             
93                 if (file_exists($sugar_config['upload_dir'] . $bean_id . rawurlencode($stored_file_name))){
94                         if (!rename($sugar_config['upload_dir'] . $bean_id . rawurlencode($stored_file_name),
95                                    $sugar_config['upload_dir'] . $bean_id)){
96                                 $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}");
97                         }
98                 }
99                 else if (file_exists($sugar_config['upload_dir'] . $bean_id . urlencode($stored_file_name))){
100                         if (!rename($sugar_config['upload_dir'] . $bean_id . urlencode($stored_file_name),
101                                    $sugar_config['upload_dir'] . $bean_id)){
102                                 $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}");
103                         }
104                 } 
105                 else if (file_exists($sugar_config['upload_dir'] . $bean_id . $stored_file_name)){
106                         if (!rename($sugar_config['upload_dir'] . $bean_id . $stored_file_name,
107                                    $sugar_config['upload_dir'] . $bean_id)){
108                                 $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}");
109                         }
110                 }
111                 else if (file_exists($sugar_config['upload_dir'] . $bean_id . $locale->translateCharset( $stored_file_name, 'UTF-8', $locale->getExportCharset() ))){
112                         if (!rename($sugar_config['upload_dir'] . $bean_id . $locale->translateCharset( $stored_file_name, 'UTF-8', $locale->getExportCharset() ), 
113                                                 $sugar_config['upload_dir'] . $bean_id)){
114                                 $GLOBALS['log']->fatal("unable to rename file in {$sugar_config['upload_dir']}");
115                         }
116                 }               
117                                 
118                 return $sugar_config['upload_dir'] . $bean_id;
119         }
120
121         /**
122          * duplicates an already uploaded file in the filesystem.
123          * @param string old_id ID of original note
124          * @param string new_id ID of new (copied) note
125          * @param string filename Filename of file (deprecated)
126          */
127         function duplicate_file($old_id, $new_id, $file_name) {
128                 global $sugar_config;
129
130                 // current file system (GUID)
131                 $source = $sugar_config['upload_dir'] . $old_id;
132                 
133                 if(!file_exists($source)) {
134                         // old-style file system (GUID.filename.extension)
135                         $oldStyleSource = $source.$file_name;
136                         if(file_exists($oldStyleSource)) {
137                                 // change to new style
138                                 if(copy($oldStyleSource, $source)) {
139                                         // delete the old
140                                         if(!unlink($oldStyleSource)) {
141                                                 $GLOBALS['log']->warn("upload_file could not unlink [ {$oldStyleSource} ]");
142                                         }
143                                 } else {
144                                         $GLOBALS['log']->warn("upload_file could not copy [ {$oldStyleSource} ] to [ {$source} ]");
145                                 }
146                         }
147                 }
148                 
149                 $destination = $sugar_config['upload_dir'] . $new_id;
150                 if(!copy($source, $destination)) {
151                         $GLOBALS['log']->warn("upload_file could not copy [ {$source} ] to [ {$destination} ]");
152                 }
153         }
154
155         /**
156          * standard PHP file-upload security measures. all variables accessed in a global context
157          * @return bool True on success
158          */
159         function confirm_upload() {
160                 global $sugar_config;
161
162                 if(!is_uploaded_file($_FILES[$this->field_name]['tmp_name'])) {
163                         return false;
164                 } elseif($_FILES[$this->field_name]['size'] > $sugar_config['upload_maxsize']) {
165                         die("ERROR: uploaded file was too big: max filesize: {$sugar_config['upload_maxsize']}");
166                 }
167
168                 if(!is_writable($sugar_config['upload_dir'])) {
169                         die("ERROR: cannot write to directory: {$sugar_config['upload_dir']} for uploads");
170                 }
171
172                 $this->mime_type =$this->getMime($_FILES[$this->field_name]);
173                 $this->stored_file_name = $this->create_stored_filename();
174                 $this->temp_file_location = $_FILES[$this->field_name]['tmp_name'];
175
176                 return true;
177         }
178
179         function getMimeSoap($filename){
180
181                 if( function_exists( 'ext2mime' ) )
182                 {
183                         $mime = ext2mime($filename);
184                 }
185                 else
186                 {
187                         $mime = ' application/octet-stream';
188                 }
189                 return $mime;
190
191         }
192         function getMime(&$_FILES_element)
193         {
194
195                 $filename = $_FILES_element['name'];
196
197                 if( $_FILES_element['type'] )
198                 {
199                         $mime = $_FILES_element['type'];
200                 }
201                 elseif( function_exists( 'mime_content_type' ) )
202                 {
203                         $mime = mime_content_type( $_FILES_element['tmp_name'] );
204                 }
205                 elseif( function_exists( 'ext2mime' ) )
206                 {
207                         $mime = ext2mime( $_FILES_element['name'] );
208                 }
209                 else
210                 {
211                         $mime = ' application/octet-stream';
212                 }
213                 return $mime;
214         }
215
216         /**
217          * gets note's filename
218          * @return string
219          */
220         function get_stored_file_name() {
221                 return $this->stored_file_name;
222         }
223
224         /**
225          * creates a file's name for preparation for saving
226          * @return string
227          */
228         function create_stored_filename() {
229                 global $sugar_config;
230                 
231                 if(!$this->use_soap) {
232                         $stored_file_name = $_FILES[$this->field_name]['name'];
233                         $this->original_file_name = $stored_file_name;
234                         
235                         /**
236                          * cn: bug 8056 - windows filesystems and IIS do not like utf8.  we are forced to urlencode() to ensure that
237                          * the file is linkable from the browser.  this will stay broken until we move to a db-storage system
238                          */
239                         if(is_windows()) {
240                                 // create a non UTF-8 name encoding
241                                 // 176 + 36 char guid = windows' maximum filename length
242                                 $end = (strlen($stored_file_name) > 176) ? 176 : strlen($stored_file_name);
243                                 $stored_file_name = substr($stored_file_name, 0, $end);
244                                 $this->original_file_name = $_FILES[$this->field_name]['name'];
245                         }
246                 } else {
247                         $stored_file_name = $this->stored_file_name;
248                         $this->original_file_name = $stored_file_name;
249                 }
250                 
251         $ext_pos = strrpos($stored_file_name, ".");
252         if($ext_pos !== false)
253                         $this->file_ext = substr($stored_file_name, $ext_pos + 1);
254         // cn: bug 6347 - fix file extension detection 
255         foreach($sugar_config['upload_badext'] as $badExt) {
256             if(strtolower($this->file_ext) == strtolower($badExt)) {
257                 $stored_file_name .= ".txt";
258                 $this->file_ext="txt";
259                 break; // no need to look for more
260             }
261         }
262                 return $stored_file_name;
263         }
264
265         /**
266          * moves uploaded temp file to permanent save location
267          * @param string bean_id ID of parent bean
268          * @return bool True on success
269          */
270         function final_move($bean_id) {
271                 global $sugar_config;
272
273         $destination = clean_path($this->get_upload_path($bean_id));
274         if($this->use_soap) {
275                 $fp = sugar_fopen($destination, 'wb');
276                 if(!fwrite($fp, $this->file)){
277                         die("ERROR: can't save file to $destination");
278                 }
279                 fclose($fp);
280                 } else {
281                         if(!move_uploaded_file($_FILES[$this->field_name]['tmp_name'], $destination)) {
282                                 die("ERROR: can't move_uploaded_file to $destination. You should try making the directory writable by the webserver");
283                         }
284                 }
285                 return true;
286         }
287
288         /**
289          * returns the path with file name to save an uploaded file
290          * @param string bean_id ID of the parent bean
291          * @return string
292          */
293         function get_upload_path($bean_id) {
294                 global $sugar_config;
295                 $file_name = $bean_id;
296                 
297                 // cn: bug 8056 - mbcs filename in urlencoding > 212 chars in Windows fails
298                 $end = (strlen($file_name) > 212) ? 212 : strlen($file_name);
299                 $ret_file_name = substr($file_name, 0, $end);
300                 
301                 return $sugar_config['upload_dir'].$ret_file_name;
302         }
303
304         /**
305          * deletes a file
306          * @param string bean_id ID of the parent bean
307          * @param string file_name File's name
308          */
309         function unlink_file($bean_id,$file_name) {
310                 global $sugar_config;
311         return unlink($sugar_config['upload_dir'].$bean_id.$file_name);
312     }
313 }
314 ?>