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>