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.
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.
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
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
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.
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.
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 ********************************************************************************/
38 /*********************************************************************************
41 ********************************************************************************/
46 var $stored_file_name;
47 var $original_file_name;
48 var $temp_file_location;
49 var $use_soap = false;
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']));
62 function set_for_soap($filename, $file) {
63 $this->stored_file_name = $filename;
64 $this->use_soap = true;
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
74 function get_url($stored_file_name,$bean_id) {
76 return UploadFile::get_file_path($stored_file_name,$bean_id);
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
85 function get_file_path($stored_file_name,$bean_id) {
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'];
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']}");
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']}");
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']}");
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']}");
118 return $sugar_config['upload_dir'] . $bean_id;
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)
127 function duplicate_file($old_id, $new_id, $file_name) {
128 global $sugar_config;
130 // current file system (GUID)
131 $source = $sugar_config['upload_dir'] . $old_id;
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)) {
140 if(!unlink($oldStyleSource)) {
141 $GLOBALS['log']->warn("upload_file could not unlink [ {$oldStyleSource} ]");
144 $GLOBALS['log']->warn("upload_file could not copy [ {$oldStyleSource} ] to [ {$source} ]");
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} ]");
156 * standard PHP file-upload security measures. all variables accessed in a global context
157 * @return bool True on success
159 function confirm_upload() {
160 global $sugar_config;
162 if(!is_uploaded_file($_FILES[$this->field_name]['tmp_name'])) {
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']}");
168 if(!is_writable($sugar_config['upload_dir'])) {
169 die("ERROR: cannot write to directory: {$sugar_config['upload_dir']} for uploads");
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'];
179 function getMimeSoap($filename){
181 if( function_exists( 'ext2mime' ) )
183 $mime = ext2mime($filename);
187 $mime = ' application/octet-stream';
192 function getMime(&$_FILES_element)
195 $filename = $_FILES_element['name'];
197 if( $_FILES_element['type'] )
199 $mime = $_FILES_element['type'];
201 elseif( function_exists( 'mime_content_type' ) )
203 $mime = mime_content_type( $_FILES_element['tmp_name'] );
205 elseif( function_exists( 'ext2mime' ) )
207 $mime = ext2mime( $_FILES_element['name'] );
211 $mime = ' application/octet-stream';
217 * gets note's filename
220 function get_stored_file_name() {
221 return $this->stored_file_name;
225 * creates a file's name for preparation for saving
228 function create_stored_filename() {
229 global $sugar_config;
231 if(!$this->use_soap) {
232 $stored_file_name = $_FILES[$this->field_name]['name'];
233 $this->original_file_name = $stored_file_name;
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
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'];
247 $stored_file_name = $this->stored_file_name;
248 $this->original_file_name = $stored_file_name;
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
262 return $stored_file_name;
266 * moves uploaded temp file to permanent save location
267 * @param string bean_id ID of parent bean
268 * @return bool True on success
270 function final_move($bean_id) {
271 global $sugar_config;
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");
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");
289 * returns the path with file name to save an uploaded file
290 * @param string bean_id ID of the parent bean
293 function get_upload_path($bean_id) {
294 global $sugar_config;
295 $file_name = $bean_id;
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);
301 return $sugar_config['upload_dir'].$ret_file_name;
306 * @param string bean_id ID of the parent bean
307 * @param string file_name File's name
309 function unlink_file($bean_id,$file_name) {
310 global $sugar_config;
311 return unlink($sugar_config['upload_dir'].$bean_id.$file_name);