1<cfsetting enablecfoutputonly="Yes"> 2<!--- 3 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 4 * Copyright (C) 2003-2007 Frederico Caldeira Knabben 5 * 6 * == BEGIN LICENSE == 7 * 8 * Licensed under the terms of any of the following licenses at your 9 * choice: 10 * 11 * - GNU General Public License Version 2 or later (the "GPL") 12 * http://www.gnu.org/licenses/gpl.html 13 * 14 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 15 * http://www.gnu.org/licenses/lgpl.html 16 * 17 * - Mozilla Public License Version 1.1 or later (the "MPL") 18 * http://www.mozilla.org/MPL/MPL-1.1.html 19 * 20 * == END LICENSE == 21 * 22 * This is the "File Uploader" for ColdFusion 5. 23 * Based on connector.cfm by Mark Woods (mark@thickpaddy.com) 24 * 25 * Note: 26 * FCKeditor requires that the connector responds with UTF-8 encoded XML. 27 * As ColdFusion 5 does not fully support UTF-8 encoding, we force ASCII 28 * file and folder names in this connector to allow CF5 send a UTF-8 29 * encoded response - code points under 127 in UTF-8 are stored using a 30 * single byte, using the same encoding as ASCII, which is damn handy. 31 * This is all grand for the English speakers, like meself, but I dunno 32 * how others are gonna take to it. Well, the previous version of this 33 * connector already did this with file names and nobody seemed to mind, 34 * so fingers-crossed nobody will mind their folder names being munged too. 35 * 36---> 37 38<cfparam name="url.command" default="QuickUpload"> 39<cfparam name="url.type" default="File"> 40<cfparam name="url.currentFolder" default="/"> 41 42<cfif not isDefined("config_included")> 43 <cfinclude template="config.cfm"> 44</cfif> 45 46<cfscript> 47 function SendUploadResults(errorNumber, fileUrl, fileName, customMsg) 48 { 49 WriteOutput('<script type="text/javascript">'); 50 WriteOutput('window.parent.OnUploadCompleted(' & errorNumber & ', "' & JSStringFormat(fileUrl) & '", "' & JSStringFormat(fileName) & '", "' & JSStringFormat(customMsg) & '");' ); 51 WriteOutput('</script>'); 52 } 53</cfscript> 54 55<cfif NOT config.enabled> 56 <cfset SendUploadResults(1, "", "", "This file uploader is disabled. Please check the ""editor/filemanager/connectors/cfm/config.cfm"" file")> 57 <cfabort> 58</cfif> 59 60<cfif isDefined("Config.ConfigAllowedCommands") and not ListFind(Config.ConfigAllowedCommands, url.command)> 61 <cfset SendUploadResults(1, "", "", "The """ & url.command & """ command isn't allowed")> 62 <cfabort> 63</cfif> 64 65<cfif isDefined("Config.ConfigAllowedTypes") and not ListFind(Config.ConfigAllowedTypes, url.type)> 66 <cfset SendUploadResults(1, "", "", "The """ & url.type & """ type isn't allowed")> 67 <cfabort> 68</cfif> 69 70<cfif find( "..", url.currentFolder)> 71 <cfset SendUploadResults(102)> 72 <cfabort> 73</cfif> 74 75<cfscript> 76 userFilesPath = config.userFilesPath; 77 78 if ( userFilesPath eq "" ) { 79 userFilesPath = "/userfiles/"; 80 } 81 82 // make sure the user files path is correctly formatted 83 userFilesPath = replace(userFilesPath, "\", "/", "ALL"); 84 userFilesPath = replace(userFilesPath, '//', '/', 'ALL'); 85 if ( right(userFilesPath,1) NEQ "/" ) { 86 userFilesPath = userFilesPath & "/"; 87 } 88 if ( left(userFilesPath,1) NEQ "/" ) { 89 userFilesPath = "/" & userFilesPath; 90 } 91 92 // make sure the current folder is correctly formatted 93 url.currentFolder = replace(url.currentFolder, "\", "/", "ALL"); 94 url.currentFolder = replace(url.currentFolder, '//', '/', 'ALL'); 95 if ( right(url.currentFolder,1) neq "/" ) { 96 url.currentFolder = url.currentFolder & "/"; 97 } 98 if ( left(url.currentFolder,1) neq "/" ) { 99 url.currentFolder = "/" & url.currentFolder; 100 } 101 102 if (find("/",getBaseTemplatePath())) { 103 fs = "/"; 104 } else { 105 fs = "\"; 106 } 107 108 // Get the base physical path to the web root for this application. The code to determine the path automatically assumes that 109 // the "FCKeditor" directory in the http request path is directly off the web root for the application and that it's not a 110 // virtual directory or a symbolic link / junction. Use the serverPath config setting to force a physical path if necessary. 111 if ( len(config.serverPath) ) { 112 serverPath = config.serverPath; 113 114 if ( right(serverPath,1) neq fs ) { 115 serverPath = serverPath & fs; 116 } 117 } else { 118 serverPath = replaceNoCase(getBaseTemplatePath(),replace(cgi.script_name,"/",fs,"all"),"") & replace(userFilesPath,"/",fs,"all"); 119 } 120 121 rootPath = left( serverPath, Len(serverPath) - Len(userFilesPath) ) ; 122</cfscript> 123<cfif url.command eq "QuickUpload"> 124 <cfset resourceTypeUrl = rereplace( replace( Config.QuickUploadPath[url.type], fs, "/", "all"), "/$", "") > 125 <cfif isDefined( "Config.QuickUploadAbsolutePath" ) 126 and structkeyexists( Config.QuickUploadAbsolutePath, url.type ) 127 and Len( Config.QuickUploadAbsolutePath[url.type] )> 128 <cfset userFilesServerPath = Config.QuickUploadAbsolutePath[url.type] & url.currentFolder> 129 <cfelse> 130 <cftry> 131 <cfset userFilesServerPath = expandpath( resourceTypeUrl ) & url.currentFolder> 132 <!--- Catch: Parameter 1 of function ExpandPath must be a relative path ---> 133 <cfcatch type="any"> 134 <cfset userFilesServerPath = rootPath & Config.QuickUploadPath[url.type] & url.currentFolder> 135 </cfcatch> 136 </cftry> 137 </cfif> 138<cfelse> 139 <cfset resourceTypeUrl = rereplace( replace( Config.FileTypesPath[url.type], fs, "/", "all"), "/$", "") > 140 <cfif isDefined( "Config.FileTypesAbsolutePath" ) 141 and structkeyexists( Config.FileTypesAbsolutePath, url.type ) 142 and Len( Config.FileTypesAbsolutePath[url.type] )> 143 <cfset userFilesServerPath = Config.FileTypesAbsolutePath[url.type] & url.currentFolder> 144 <cfelse> 145 <cftry> 146 <cfset userFilesServerPath = expandpath( resourceTypeUrl ) & url.currentFolder> 147 <!--- Catch: Parameter 1 of function ExpandPath must be a relative path ---> 148 <cfcatch type="any"> 149 <cfset userFilesServerPath = rootPath & Config.FileTypesPath[url.type] & url.currentFolder> 150 </cfcatch> 151 </cftry> 152 </cfif> 153</cfif> 154 155<cfset userFilesServerPath = replace( userFilesServerPath, "/", fs, "all" ) > 156<!--- get rid of double directory separators ---> 157<cfset userFilesServerPath = replace( userFilesServerPath, fs & fs, fs, "all") > 158 159<!--- create resource type directory if not exists ---> 160<cfset resourceTypeDirectory = left( userFilesServerPath, Len(userFilesServerPath) - Len(url.currentFolder) )> 161 162<cfif not directoryexists( resourceTypeDirectory )> 163 164 <cfset currentPath = ""> 165 <cftry> 166 <cfloop list="#resourceTypeDirectory#" index="name" delimiters="#fs#"> 167 <cfif currentPath eq "" and fs eq "\"> 168 <!--- Without checking this, we would have in Windows \C:\ ---> 169 <cfif not directoryExists(name)> 170 <cfdirectory action="create" directory="#name#" mode="755"> 171 </cfif> 172 <cfelse> 173 <cfif not directoryExists(currentPath & fs & name)> 174 <cfdirectory action="create" directory="#currentPath##fs##name#" mode="755"> 175 </cfif> 176 </cfif> 177 178 <cfif fs eq "\" and currentPath eq ""> 179 <cfset currentPath = name> 180 <cfelse> 181 <cfset currentPath = currentPath & fs & name> 182 </cfif> 183 </cfloop> 184 185 <cfcatch type="any"> 186 187 <!--- this should only occur as a result of a permissions problem ---> 188 <cfset SendUploadResults(103)> 189 <cfabort> 190 191 </cfcatch> 192 193 </cftry> 194</cfif> 195 196<cfset currentFolderPath = userFilesServerPath> 197<cfset resourceType = url.type> 198 199<cfset fileName = ""> 200<cfset fileExt = ""> 201 202<!--- Can be overwritten. The last value will be sent with the result ---> 203<cfset customMsg = ""> 204 205<cftry> 206 <!--- first upload the file with an unique filename ---> 207 <cffile action="upload" 208 fileField="NewFile" 209 destination="#currentFolderPath#" 210 nameConflict="makeunique" 211 mode="644" 212 attributes="normal"> 213 214 <cfif cffile.fileSize EQ 0> 215 <cfthrow> 216 </cfif> 217 218 <cfset lAllowedExtensions = config.allowedExtensions[#resourceType#]> 219 <cfset lDeniedExtensions = config.deniedExtensions[#resourceType#]> 220 221 <cfif ( len(lAllowedExtensions) and not listFindNoCase(lAllowedExtensions,cffile.ServerFileExt) ) 222 or ( len(lDeniedExtensions) and listFindNoCase(lDeniedExtensions,cffile.ServerFileExt) )> 223 224 <cfset errorNumber = "202"> 225 <cffile action="delete" file="#cffile.ServerDirectory##fs##cffile.ServerFile#"> 226 227 <cfelse> 228 229 <cfscript> 230 errorNumber = 0; 231 fileName = cffile.ClientFileName ; 232 fileExt = cffile.ServerFileExt ; 233 fileExisted = false ; 234 235 // munge filename for html download. Only a-z, 0-9, _, - and . are allowed 236 if( reFind("[^A-Za-z0-9_\-\.]", fileName) ) { 237 fileName = reReplace(fileName, "[^A-Za-z0-9\-\.]", "_", "ALL"); 238 fileName = reReplace(fileName, "_{2,}", "_", "ALL"); 239 fileName = reReplace(fileName, "([^_]+)_+$", "\1", "ALL"); 240 fileName = reReplace(fileName, "$_([^_]+)$", "\1", "ALL"); 241 } 242 243 // remove additional dots from file name 244 if( isDefined("Config.ForceSingleExtension") and Config.ForceSingleExtension ) 245 fileName = replace( fileName, '.', "_", "all" ) ; 246 247 // When the original filename already exists, add numbers (0), (1), (2), ... at the end of the filename. 248 if( compare( cffile.ServerFileName, fileName ) ) { 249 counter = 0; 250 tmpFileName = fileName; 251 while( fileExists("#currentFolderPath##fileName#.#fileExt#") ) { 252 fileExisted = true ; 253 counter = counter + 1 ; 254 fileName = tmpFileName & '(#counter#)' ; 255 } 256 } 257 </cfscript> 258 259 <!--- Rename the uploaded file, if neccessary ---> 260 <cfif compare(cffile.ServerFileName,fileName)> 261 262 <cfif fileExisted> 263 <cfset errorNumber = "201"> 264 </cfif> 265 <cffile 266 action="rename" 267 source="#currentFolderPath##cffile.ServerFileName#.#cffile.ServerFileExt#" 268 destination="#currentFolderPath##fileName#.#fileExt#" 269 mode="644" 270 attributes="normal"> 271 272 </cfif> 273 274 </cfif> 275 276 <cfcatch type="any"> 277 278 <cfset errorNumber = "1"> 279 <cfset customMsg = cfcatch.message > 280 281 </cfcatch> 282</cftry> 283 284<cfif errorNumber EQ 0> 285 <!--- file was uploaded succesfully ---> 286 <cfset SendUploadResults(errorNumber, '#resourceTypeUrl##url.currentFolder##fileName#.#fileExt#', "", "")> 287 <cfabort> 288<cfelseif errorNumber EQ 201> 289 <!--- file was changed (201), submit the new filename ---> 290 <cfset SendUploadResults(errorNumber, '#resourceTypeUrl##url.currentFolder##fileName#.#fileExt#', replace( fileName & "." & fileExt, "'", "\'", "ALL"), customMsg)> 291 <cfabort> 292<cfelse> 293 <!--- An error occured(202). Submit only the error code and a message (if available). ---> 294 <cfset SendUploadResults(errorNumber, '', '', customMsg)> 295 <cfabort> 296</cfif>