Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/connector.aspx
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/connector.aspx	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/connector.aspx	(revision 315)
@@ -0,0 +1,30 @@
+<%@ Page language="c#" Inherits="FredCK.FCKeditorV2.FileBrowserConnector" AutoEventWireup="false" %>
+<%--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the File Browser Connector for ASP.NET.
+ *
+ * The code of this page if included in the FCKeditor.Net package,
+ * in the FredCK.FCKeditorV2.dll assembly file. So to use it you must
+ * include that DLL in your "bin" directory.
+ *
+ * To download the FCKeditor.Net package, go to our official web site:
+ * http://www.fckeditor.net
+--%>
Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/upload.aspx
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/upload.aspx	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/aspx/upload.aspx	(revision 315)
@@ -0,0 +1,30 @@
+<%@ Page language="c#" Inherits="FredCK.FCKeditorV2.Uploader" AutoEventWireup="false" %>
+<%--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the Uploader for ASP.NET.
+ *
+ * The code of this page if included in the FCKeditor.Net package,
+ * in the FredCK.FCKeditorV2.dll assemblyfile. So to use it you must
+ * include that DLL in your "bin" directory.
+ *
+ * To download the FCKeditor.Net package, go to our official web site:
+ * http://www.fckeditor.net
+--%>
Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/config.lasso
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/config.lasso	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/config.lasso	(revision 315)
@@ -0,0 +1,65 @@
+[//lasso
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Configuration file for the File Manager Connector for Lasso.
+ */
+
+    /*.....................................................................
+    The connector uses the file tags, which require authentication. Enter a
+    valid username and password from Lasso admin for a group with file tags
+    permissions for uploads and the path you define in UserFilesPath below.
+    */
+
+	var('connection') = array(
+		-username='xxxxxxxx',
+		-password='xxxxxxxx'
+	);
+
+
+    /*.....................................................................
+    Set the base path for files that users can upload and browse (relative
+    to server root).
+
+    Set which file extensions are allowed and/or denied for each file type.
+    */
+	var('config') = map(
+		'Enabled' = false,
+		'UserFilesPath' = '/userfiles/',
+		'Subdirectories' = map(
+			'File' = 'File/',
+			'Image' = 'Image/',
+			'Flash' = 'Flash/',
+			'Media' = 'Media/'
+		),
+		'AllowedExtensions' = map(
+			'File' = array(),
+			'Image' = array('jpg','gif','jpeg','png'),
+			'Flash' = array('swf','fla'),
+			'Media' = array('swf','fla','jpg','gif','jpeg','png','avi','mpg','mpeg')
+		),
+		'DeniedExtensions' = map(
+			'File' = array('html','htm','php','php2','php3','php4','php5','phtml','pwml','inc','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','com','dll','vbs','js','reg','cgi','lasso','lassoapp','htaccess','asis','sh','shtml','shtm','phtm'),
+			'Image' = array(),
+			'Flash' = array(),
+			'Media' = array()
+		)
+	);
+]
Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/connector.lasso
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/connector.lasso	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/connector.lasso	(revision 315)
@@ -0,0 +1,249 @@
+[//lasso
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the File Manager Connector for Lasso.
+ */
+
+    /*.....................................................................
+    Include global configuration. See config.lasso for details.
+    */
+	include('config.lasso');
+
+
+    /*.....................................................................
+    Translate current date/time to GMT for custom header.
+    */
+	var('headerDate') = date_localtogmt(date)->format('%a, %d %b %Y %T GMT');
+
+
+    /*.....................................................................
+    Convert query string parameters to variables and initialize output.
+    */
+	var(
+		'Command'		=	action_param('Command'),
+		'Type'			=	action_param('Type'),
+		'CurrentFolder'	=	action_param('CurrentFolder'),
+		'ServerPath'	=	action_param('ServerPath'),
+		'NewFolderName'	=	action_param('NewFolderName'),
+		'NewFile'		=	null,
+		'NewFileName'	=	string,
+		'OrigFilePath'	=	string,
+		'NewFilePath'	=	string,
+		'commandData'	=	string,
+		'folders'		=	'\t<Folders>\n',
+		'files'			=	'\t<Files>\n',
+		'errorNumber'	=	integer,
+		'responseType'	=	'xml',
+		'uploadResult'	=	'0'
+	);
+
+
+    /*.....................................................................
+    Calculate the path to the current folder.
+    */
+	$ServerPath == '' ? $ServerPath = $config->find('UserFilesPath');
+
+	var('currentFolderURL' = $ServerPath
+		+ $config->find('Subdirectories')->find(action_param('Type'))
+		+ action_param('CurrentFolder')
+	);
+
+
+    /*.....................................................................
+    Build the appropriate response per the 'Command' parameter. Wrap the
+    entire process in an inline for file tag permissions.
+    */
+	inline($connection);
+		select($Command);
+            /*.............................................................
+            List all subdirectories in the 'Current Folder' directory.
+            */
+			case('GetFolders');
+				$commandData += '\t<Folders>\n';
+
+				iterate(file_listdirectory($currentFolderURL), local('this'));
+					#this->endswith('/') ? $commandData += '\t\t<Folder name="' + #this->removetrailing('/')& + '" />\n';
+				/iterate;
+
+				$commandData += '\t</Folders>\n';
+
+
+            /*.............................................................
+            List both files and folders in the 'Current Folder' directory.
+            Include the file sizes in kilobytes.
+            */
+			case('GetFoldersAndFiles');
+				iterate(file_listdirectory($currentFolderURL), local('this'));
+					if(#this->endswith('/'));
+						$folders += '\t\t<Folder name="' + #this->removetrailing('/')& + '" />\n';
+					else;
+						local('size') = file_getsize($currentFolderURL + #this) / 1024;
+						$files += '\t\t<File name="' + #this + '" size="' + #size + '" />\n';
+					/if;
+				/iterate;
+
+				$folders += '\t</Folders>\n';
+				$files += '\t</Files>\n';
+
+				$commandData += $folders + $files;
+
+
+            /*.............................................................
+            Create a directory 'NewFolderName' within the 'Current Folder.'
+            */
+			case('CreateFolder');
+				var('newFolder' = $currentFolderURL + $NewFolderName + '/');
+				file_create($newFolder);
+
+
+                /*.........................................................
+                Map Lasso's file error codes to FCKEditor's error codes.
+                */
+				select(file_currenterror( -errorcode));
+					case(0);
+						$errorNumber = 0;
+					case( -9983);
+						$errorNumber = 101;
+					case( -9976);
+						$errorNumber = 102;
+					case( -9977);
+						$errorNumber = 102;
+					case( -9961);
+						$errorNumber = 103;
+					case;
+						$errorNumber = 110;
+				/select;
+
+				$commandData += '<Error number="' + $errorNumber + '" />\n';
+
+
+            /*.............................................................
+            Process an uploaded file.
+            */
+			case('FileUpload');
+                /*.........................................................
+                This is the only command that returns an HTML response.
+                */
+				$responseType = 'html';
+
+
+                /*.........................................................
+                Was a file actually uploaded?
+                */
+				file_uploads->size ? $NewFile = file_uploads->get(1) | $uploadResult = '202';
+
+				if($uploadResult == '0');
+                    /*.....................................................
+                    Split the file's extension from the filename in order
+                    to follow the API's naming convention for duplicate
+                    files. (Test.txt, Test(1).txt, Test(2).txt, etc.)
+                    */
+					$NewFileName = $NewFile->find('OrigName');
+					$OrigFilePath = $currentFolderURL + $NewFileName;
+					$NewFilePath = $OrigFilePath;
+					local('fileExtension') = '.' + $NewFile->find('OrigExtension');
+					local('shortFileName') = $NewFileName->removetrailing(#fileExtension)&;
+
+
+                    /*.....................................................
+                    Make sure the file extension is allowed.
+                    */
+					if($config->find('DeniedExtensions')->find($Type) >> $NewFile->find('OrigExtension'));
+						$uploadResult = '202';
+					else;
+                        /*.................................................
+                        Rename the target path until it is unique.
+                        */
+						while(file_exists($NewFilePath));
+							$NewFilePath = $currentFolderURL + #shortFileName + '(' + loop_count + ')' + #fileExtension;
+						/while;
+
+
+                        /*.................................................
+                        Copy the uploaded file to its final location.
+                        */
+						file_copy($NewFile->find('path'), $NewFilePath);
+
+
+                        /*.................................................
+                        Set the error code for the response. Note whether
+                        the file had to be renamed.
+                        */
+						select(file_currenterror( -errorcode));
+							case(0);
+								$OrigFilePath != $NewFilePath ? $uploadResult = '201, \'' + $NewFilePath->split('/')->last + '\'';
+							case;
+								$uploadResult = '202';
+						/select;
+					/if;
+				/if;
+
+
+                /*.........................................................
+                Set the HTML response.
+                */
+				$__html_reply__ = '\
+<script type="text/javascript">
+	window.parent.frames[\'frmUpload\'].OnUploadCompleted(' + $uploadResult + ');
+</script>
+				';
+		/select;
+	/inline;
+
+
+    /*.....................................................................
+    Send a custom header for xml responses.
+    */
+	if($responseType == 'xml');
+		header;
+]
+HTTP/1.0 200 OK
+Date: [$headerDate]
+Server: Lasso Professional [lasso_version( -lassoversion)]
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Last-Modified: [$headerDate]
+Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
+Pragma: no-cache
+Keep-Alive: timeout=15, max=98
+Connection: Keep-Alive
+Content-Type: text/xml; charset=utf-8
+[//lasso
+		/header;
+
+
+        /*.................................................................
+        Set the content type encoding for Lasso.
+        */
+		content_type('text/xml; charset=utf-8');
+
+
+        /*.................................................................
+        Wrap the response as XML and output.
+        */
+		$__html_reply__ = '\
+<?xml version="1.0" encoding="utf-8" ?>
+<Connector command="' + $Command + '" resourceType="' + $Type + '">
+	<CurrentFolder path="' + $CurrentFolder + '" url="' + $currentFolderURL + '" />
+' + $commandData + '
+</Connector>
+		';
+	/if;
+]
Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/upload.lasso
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/upload.lasso	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/lasso/upload.lasso	(revision 315)
@@ -0,0 +1,157 @@
+[//lasso
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the "File Uploader" for Lasso.
+ */
+
+    /*.....................................................................
+    Include global configuration. See config.lasso for details.
+    */
+	include('config.lasso');
+
+
+    /*.....................................................................
+    Convert query string parameters to variables and initialize output.
+    */
+	var(
+		'Type'			=	action_param('Type'),
+		'CurrentFolder'	=	action_param('CurrentFolder'),
+		'ServerPath'	=	action_param('ServerPath'),
+		'NewFile'		=	null,
+		'NewFileName'	=	string,
+		'OrigFilePath'	=	string,
+		'NewFilePath'	=	string,
+		'errorNumber'	=	0,
+		'customMsg'		=	''
+	);
+
+	$Type == '' ? $Type = 'File';
+
+
+    /*.....................................................................
+    Calculate the path to the current folder.
+    */
+	$ServerPath == '' ? $ServerPath = $config->find('UserFilesPath');
+
+	var('currentFolderURL' = $ServerPath
+		+ $config->find('Subdirectories')->find(action_param('Type'))
+		+ action_param('CurrentFolder')
+	);
+
+
+	/*.....................................................................
+	Custom tag sets the HTML response.
+	*/
+
+	define_tag(
+		'sendresults',
+		-namespace='fck_',
+		-priority='replace',
+		-required='errorNumber',
+		-type='integer',
+		-optional='fileUrl',
+		-type='string',
+		-optional='fileName',
+		-type='string',
+		-optional='customMsg',
+		-type='string',
+		-description='Sets the HTML response for the FCKEditor Quick Upload feature.'
+	);
+		$__html_reply__ = '\
+<script type="text/javascript">
+	window.parent.OnUploadCompleted(' + #errorNumber + ',"'
+		+ string_replace(#fileUrl, -find='"', -replace='\\"') + '","'
+		+ string_replace(#fileName, -find='"', -replace='\\"') + '","'
+		+ string_replace(#customMsg, -find='"', -replace='\\"') + '");
+</script>
+		';
+	/define_tag;
+
+
+	if($config->find('Enabled'));
+		/*.................................................................
+		Process an uploaded file.
+		*/
+		inline($connection);
+			/*.............................................................
+			Was a file actually uploaded?
+			*/
+			file_uploads->size ? $NewFile = file_uploads->get(1) | $errorNumber = 202;
+
+			if($errorNumber == 0);
+				/*.........................................................
+				Split the file's extension from the filename in order
+				to follow the API's naming convention for duplicate
+				files. (Test.txt, Test(1).txt, Test(2).txt, etc.)
+				*/
+				$NewFileName = $NewFile->find('OrigName');
+				$OrigFilePath = $currentFolderURL + $NewFileName;
+				$NewFilePath = $OrigFilePath;
+				local('fileExtension') = '.' + $NewFile->find('OrigExtension');
+				local('shortFileName') = $NewFileName->removetrailing(#fileExtension)&;
+
+
+				/*.........................................................
+				Make sure the file extension is allowed.
+				*/
+
+				if($config->find('DeniedExtensions')->find($Type) >> $NewFile->find('OrigExtension'));
+					$errorNumber = 202;
+				else;
+					/*.....................................................
+					Rename the target path until it is unique.
+					*/
+					while(file_exists($NewFilePath));
+						$NewFileName = #shortFileName + '(' + loop_count + ')' + #fileExtension;
+						$NewFilePath = $currentFolderURL + $NewFileName;
+					/while;
+
+
+					/*.....................................................
+					Copy the uploaded file to its final location.
+					*/
+					file_copy($NewFile->find('path'), $NewFilePath);
+
+
+					/*.....................................................
+					Set the error code for the response.
+					*/
+					select(file_currenterror( -errorcode));
+						case(0);
+							$OrigFilePath != $NewFilePath ? $errorNumber = 201;
+						case;
+							$errorNumber = 202;
+					/select;
+				/if;
+			/if;
+		/inline;
+	else;
+		$errorNumber = 1;
+		$customMsg = 'This file uploader is disabled. Please check the "editor/filemanager/upload/lasso/config.lasso" file.';
+	/if;
+
+	fck_sendresults(
+		-errorNumber=$errorNumber,
+		-fileUrl=$NewFilePath,
+		-fileName=$NewFileName,
+		-customMsg=$customMsg
+	);
+]
Index: /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/py/connector.py
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/py/connector.py	(revision 315)
+++ /FCKeditor/branches/developers/alfonsoml/editor/filemanager/connectors/py/connector.py	(revision 315)
@@ -0,0 +1,785 @@
+#!/usr/bin/env python
+
+"""
+FCKeditor - The text editor for Internet - http://www.fckeditor.net
+Copyright (C) 2003-2007 Frederico Caldeira Knabben
+
+== BEGIN LICENSE ==
+
+Licensed under the terms of any of the following licenses at your
+choice:
+
+ - GNU General Public License Version 2 or later (the "GPL")
+   http://www.gnu.org/licenses/gpl.html
+
+ - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+   http://www.gnu.org/licenses/lgpl.html
+
+ - Mozilla Public License Version 1.1 or later (the "MPL")
+   http://www.mozilla.org/MPL/MPL-1.1.html
+
+== END LICENSE ==
+
+Connector for Python.
+
+Tested With:
+Standard:
+	Python 2.3.3
+Zope:
+	Zope Version: (Zope 2.8.1-final, python 2.3.5, linux2)
+	Python Version: 2.3.5 (#4, Mar 10 2005, 01:40:25)
+		[GCC 3.3.3 20040412 (Red Hat Linux 3.3.3-7)]
+	System Platform: linux2
+"""
+
+"""
+Author Notes (04 December 2005):
+This module has gone through quite a few phases of change.  Obviously,
+I am only supporting that part of the code that I use.  Initially
+I had the upload directory as a part of zope (ie. uploading files
+directly into Zope), before realising that there were too many
+complex intricacies within Zope to deal with.  Zope is one ugly piece
+of code.  So I decided to complement Zope by an Apache server (which
+I had running anyway, and doing nothing).  So I mapped all uploads
+from an arbitrary server directory to an arbitrary web directory.
+All the FCKeditor uploading occurred this way, and I didn't have to
+stuff around with fiddling with Zope objects and the like (which are
+terribly complex and something you don't want to do - trust me).
+
+Maybe a Zope expert can touch up the Zope components.  In the end,
+I had FCKeditor loaded in Zope (probably a bad idea as well), and
+I replaced the connector.py with an alias to a server module.
+Right now, all Zope components will simple remain as is because
+I've had enough of Zope.
+
+See notes right at the end of this file for how I aliased out of Zope.
+
+Anyway, most of you probably wont use Zope, so things are pretty
+simple in that regard.
+
+Typically, SERVER_DIR is the root of WEB_DIR (not necessarily).
+Most definitely, SERVER_USERFILES_DIR points to WEB_USERFILES_DIR.
+"""
+
+import cgi
+import re
+import os
+import string
+
+"""
+escape
+
+Converts the special characters '<', '>', and '&'.
+
+RFC 1866 specifies that these characters be represented
+in HTML as &lt; &gt; and &amp; respectively. In Python
+1.5 we use the new string.replace() function for speed.
+"""
+def escape(text, replace=string.replace):
+    text = replace(text, '&', '&amp;') # must be done 1st
+    text = replace(text, '<', '&lt;')
+    text = replace(text, '>', '&gt;')
+    text = replace(text, '"', '&quot;')
+    return text
+
+"""
+getFCKeditorConnector
+
+Creates a new instance of an FCKeditorConnector, and runs it
+"""
+def getFCKeditorConnector(context=None):
+	# Called from Zope.  Passes the context through
+	connector = FCKeditorConnector(context=context)
+	return connector.run()
+
+
+"""
+FCKeditorRequest
+
+A wrapper around the request object
+Can handle normal CGI request, or a Zope request
+Extend as required
+"""
+class FCKeditorRequest(object):
+	def __init__(self, context=None):
+		if (context is not None):
+			r = context.REQUEST
+		else:
+			r = cgi.FieldStorage()
+		self.context = context
+		self.request = r
+
+	def isZope(self):
+		if (self.context is not None):
+			return True
+		return False
+
+	def has_key(self, key):
+		return self.request.has_key(key)
+
+	def get(self, key, default=None):
+		value = None
+		if (self.isZope()):
+			value = self.request.get(key, default)
+		else:
+			if key in self.request.keys():
+				value = self.request[key].value
+			else:
+				value = default
+		return value
+
+"""
+FCKeditorConnector
+
+The connector class
+"""
+class FCKeditorConnector(object):
+	# Configuration for FCKEditor
+	# can point to another server here, if linked correctly
+	#WEB_HOST = "http://127.0.0.1/"
+	WEB_HOST = ""
+	SERVER_DIR = "/var/www/html/"
+
+	WEB_USERFILES_FOLDER = WEB_HOST + "upload/"
+	SERVER_USERFILES_FOLDER = SERVER_DIR + "upload/"
+
+	# Allow access (Zope)
+	__allow_access_to_unprotected_subobjects__ = 1
+	# Class Attributes
+	parentFolderRe = re.compile("[\/][^\/]+[\/]?$")
+
+	"""
+	Constructor
+	"""
+	def __init__(self, context=None):
+		# The given root path will NOT be shown to the user
+		# Only the userFilesPath will be shown
+
+		# Instance Attributes
+		self.context = context
+		self.request = FCKeditorRequest(context=context)
+		self.rootPath = self.SERVER_DIR
+		self.userFilesFolder = self.SERVER_USERFILES_FOLDER
+		self.webUserFilesFolder = self.WEB_USERFILES_FOLDER
+
+		# Enables / Disables the connector
+		self.enabled = False # Set to True to enable this connector
+
+		# These are instance variables
+		self.zopeRootContext = None
+		self.zopeUploadContext = None
+
+		# Copied from php module =)
+		self.allowedExtensions = {
+				"File": None,
+				"Image": None,
+				"Flash": None,
+				"Media": None
+				}
+		self.deniedExtensions = {
+				"File": [ "html","htm","php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess","asis","sh","shtml","shtm","phtm" ],
+				"Image": [ "html","htm","php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess","asis","sh","shtml","shtm","phtm" ],
+				"Flash": [ "html","htm","php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess","asis","sh","shtml","shtm","phtm" ],
+				"Media": [ "html","htm","php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess","asis","sh","shtml","shtm","phtm" ]
+				}
+
+	"""
+	Zope specific functions
+	"""
+	def isZope(self):
+		# The context object is the zope object
+		if (self.context is not None):
+			return True
+		return False
+
+	def getZopeRootContext(self):
+		if self.zopeRootContext is None:
+			self.zopeRootContext = self.context.getPhysicalRoot()
+		return self.zopeRootContext
+
+	def getZopeUploadContext(self):
+		if self.zopeUploadContext is None:
+			folderNames = self.userFilesFolder.split("/")
+			c = self.getZopeRootContext()
+			for folderName in folderNames:
+				if (folderName <> ""):
+					c = c[folderName]
+			self.zopeUploadContext = c
+		return self.zopeUploadContext
+
+	"""
+	Generic manipulation functions
+	"""
+	def getUserFilesFolder(self):
+		return self.userFilesFolder
+
+	def getWebUserFilesFolder(self):
+		return self.webUserFilesFolder
+
+	def getAllowedExtensions(self, resourceType):
+		return self.allowedExtensions[resourceType]
+
+	def getDeniedExtensions(self, resourceType):
+		return self.deniedExtensions[resourceType]
+
+	def removeFromStart(self, string, char):
+		return string.lstrip(char)
+
+	def removeFromEnd(self, string, char):
+		return string.rstrip(char)
+
+	def convertToXmlAttribute(self, value):
+		if (value is None):
+			value = ""
+		return escape(value)
+
+	def convertToPath(self, path):
+		if (path[-1] <> "/"):
+			return path + "/"
+		else:
+			return path
+
+	def getUrlFromPath(self, resourceType, path):
+		if (resourceType is None) or (resourceType == ''):
+			url = "%s%s" % (
+					self.removeFromEnd(self.getUserFilesFolder(), '/'),
+					path
+					)
+		else:
+			url = "%s%s%s" % (
+					self.getUserFilesFolder(),
+					resourceType,
+					path
+					)
+		return url
+
+	def getWebUrlFromPath(self, resourceType, path):
+		if (resourceType is None) or (resourceType == ''):
+			url = "%s%s" % (
+					self.removeFromEnd(self.getWebUserFilesFolder(), '/'),
+					path
+					)
+		else:
+			url = "%s%s%s" % (
+					self.getWebUserFilesFolder(),
+					resourceType,
+					path
+					)
+		return url
+
+	def removeExtension(self, fileName):
+		index = fileName.rindex(".")
+		newFileName = fileName[0:index]
+		return newFileName
+
+	def getExtension(self, fileName):
+		index = fileName.rindex(".") + 1
+		fileExtension = fileName[index:]
+		return fileExtension
+
+	def getParentFolder(self, folderPath):
+		parentFolderPath = self.parentFolderRe.sub('', folderPath)
+		return parentFolderPath
+
+	"""
+	serverMapFolder
+
+	Purpose: works out the folder map on the server
+	"""
+	def serverMapFolder(self, resourceType, folderPath):
+		# Get the resource type directory
+		resourceTypeFolder = "%s%s/" % (
+				self.getUserFilesFolder(),
+				resourceType
+				)
+		# Ensure that the directory exists
+		self.createServerFolder(resourceTypeFolder)
+
+		# Return the resource type directory combined with the
+		# required path
+		return "%s%s" % (
+				resourceTypeFolder,
+				self.removeFromStart(folderPath, '/')
+				)
+
+	"""
+	createServerFolder
+
+	Purpose: physically creates a folder on the server
+	"""
+	def createServerFolder(self, folderPath):
+		# Check if the parent exists
+		parentFolderPath = self.getParentFolder(folderPath)
+		if not(os.path.exists(parentFolderPath)):
+			errorMsg = self.createServerFolder(parentFolderPath)
+			if errorMsg is not None:
+				return errorMsg
+		# Check if this exists
+		if not(os.path.exists(folderPath)):
+			os.mkdir(folderPath)
+			os.chmod(folderPath, 0755)
+			errorMsg = None
+		else:
+			if os.path.isdir(folderPath):
+				errorMsg = None
+			else:
+				raise "createServerFolder: Non-folder of same name already exists"
+		return errorMsg
+
+
+	"""
+	getRootPath
+
+	Purpose: returns the root path on the server
+	"""
+	def getRootPath(self):
+		return self.rootPath
+
+	"""
+	setXmlHeaders
+
+	Purpose: to prepare the headers for the xml to return
+	"""
+	def setXmlHeaders(self):
+		#now = self.context.BS_get_now()
+		#yesterday = now - 1
+		self.setHeader("Content-Type", "text/xml")
+		#self.setHeader("Expires", yesterday)
+		#self.setHeader("Last-Modified", now)
+		#self.setHeader("Cache-Control", "no-store, no-cache, must-revalidate")
+		self.printHeaders()
+		return
+
+	def setHeader(self, key, value):
+		if (self.isZope()):
+			self.context.REQUEST.RESPONSE.setHeader(key, value)
+		else:
+			print "%s: %s" % (key, value)
+		return
+
+	def printHeaders(self):
+		# For non-Zope requests, we need to print an empty line
+		# to denote the end of headers
+		if (not(self.isZope())):
+			print ""
+
+	"""
+	createXmlFooter
+
+	Purpose: returns the xml header
+	"""
+	def createXmlHeader(self, command, resourceType, currentFolder):
+		self.setXmlHeaders()
+		s = ""
+		# Create the XML document header
+		s += """<?xml version="1.0" encoding="utf-8" ?>"""
+		# Create the main connector node
+		s += """<Connector command="%s" resourceType="%s">""" % (
+				command,
+				resourceType
+				)
+		# Add the current folder node
+		s += """<CurrentFolder path="%s" url="%s" />""" % (
+				self.convertToXmlAttribute(currentFolder),
+				self.convertToXmlAttribute(
+					self.getWebUrlFromPath(
+						resourceType,
+						currentFolder
+						)
+					),
+				)
+		return s
+
+	"""
+	createXmlFooter
+
+	Purpose: returns the xml footer
+	"""
+	def createXmlFooter(self):
+		s = """</Connector>"""
+		return s
+
+	"""
+	sendError
+
+	Purpose: in the event of an error, return an xml based error
+	"""
+	def sendError(self, number, text):
+		self.setXmlHeaders()
+		s = ""
+		# Create the XML document header
+		s += """<?xml version="1.0" encoding="utf-8" ?>"""
+		s += """<Connector>"""
+		s += """<Error number="%s" text="%s" />""" % (number, text)
+		s += """</Connector>"""
+		return s
+
+	"""
+	getFolders
+
+	Purpose: command to recieve a list of folders
+	"""
+	def getFolders(self, resourceType, currentFolder):
+		if (self.isZope()):
+			return self.getZopeFolders(resourceType, currentFolder)
+		else:
+			return self.getNonZopeFolders(resourceType, currentFolder)
+
+	def getZopeFolders(self, resourceType, currentFolder):
+		# Open the folders node
+		s = ""
+		s += """<Folders>"""
+		zopeFolder = self.findZopeFolder(resourceType, currentFolder)
+		for (name, o) in zopeFolder.objectItems(["Folder"]):
+			s += """<Folder name="%s" />""" % (
+					self.convertToXmlAttribute(name)
+					)
+		# Close the folders node
+		s += """</Folders>"""
+		return s
+
+	def getNonZopeFolders(self, resourceType, currentFolder):
+		# Map the virtual path to our local server
+		serverPath = self.serverMapFolder(resourceType, currentFolder)
+		# Open the folders node
+		s = ""
+		s += """<Folders>"""
+		for someObject in os.listdir(serverPath):
+			someObjectPath = os.path.join(serverPath, someObject)
+			if os.path.isdir(someObjectPath):
+				s += """<Folder name="%s" />""" % (
+						self.convertToXmlAttribute(someObject)
+						)
+		# Close the folders node
+		s += """</Folders>"""
+		return s
+
+	"""
+	getFoldersAndFiles
+
+	Purpose: command to recieve a list of folders and files
+	"""
+	def getFoldersAndFiles(self, resourceType, currentFolder):
+		if (self.isZope()):
+			return self.getZopeFoldersAndFiles(resourceType, currentFolder)
+		else:
+			return self.getNonZopeFoldersAndFiles(resourceType, currentFolder)
+
+	def getNonZopeFoldersAndFiles(self, resourceType, currentFolder):
+		# Map the virtual path to our local server
+		serverPath = self.serverMapFolder(resourceType, currentFolder)
+		# Open the folders / files node
+		folders = """<Folders>"""
+		files = """<Files>"""
+		for someObject in os.listdir(serverPath):
+			someObjectPath = os.path.join(serverPath, someObject)
+			if os.path.isdir(someObjectPath):
+				folders += """<Folder name="%s" />""" % (
+						self.convertToXmlAttribute(someObject)
+						)
+			elif os.path.isfile(someObjectPath):
+				size = os.path.getsize(someObjectPath)
+				files += """<File name="%s" size="%s" />""" % (
+						self.convertToXmlAttribute(someObject),
+						os.path.getsize(someObjectPath)
+						)
+		# Close the folders / files node
+		folders += """</Folders>"""
+		files += """</Files>"""
+		# Return it
+		s = folders + files
+		return s
+
+	def getZopeFoldersAndFiles(self, resourceType, currentFolder):
+		folders = self.getZopeFolders(resourceType, currentFolder)
+		files = self.getZopeFiles(resourceType, currentFolder)
+		s = folders + files
+		return s
+
+	def getZopeFiles(self, resourceType, currentFolder):
+		# Open the files node
+		s = ""
+		s += """<Files>"""
+		zopeFolder = self.findZopeFolder(resourceType, currentFolder)
+		for (name, o) in zopeFolder.objectItems(["File","Image"]):
+			s += """<File name="%s" size="%s" />""" % (
+					self.convertToXmlAttribute(name),
+					((o.get_size() / 1024) + 1)
+					)
+		# Close the files node
+		s += """</Files>"""
+		return s
+
+	def findZopeFolder(self, resourceType, folderName):
+		# returns the context of the resource / folder
+		zopeFolder = self.getZopeUploadContext()
+		folderName = self.removeFromStart(folderName, "/")
+		folderName = self.removeFromEnd(folderName, "/")
+		if (resourceType <> ""):
+			try:
+				zopeFolder = zopeFolder[resourceType]
+			except:
+				zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=resourceType, title=resourceType)
+				zopeFolder = zopeFolder[resourceType]
+		if (folderName <> ""):
+			folderNames = folderName.split("/")
+			for folderName in folderNames:
+				zopeFolder = zopeFolder[folderName]
+		return zopeFolder
+
+	"""
+	createFolder
+
+	Purpose: command to create a new folder
+	"""
+	def createFolder(self, resourceType, currentFolder):
+		if (self.isZope()):
+			return self.createZopeFolder(resourceType, currentFolder)
+		else:
+			return self.createNonZopeFolder(resourceType, currentFolder)
+
+	def createZopeFolder(self, resourceType, currentFolder):
+		# Find out where we are
+		zopeFolder = self.findZopeFolder(resourceType, currentFolder)
+		errorNo = 0
+		errorMsg = ""
+		if self.request.has_key("NewFolderName"):
+			newFolder = self.request.get("NewFolderName", None)
+			zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=newFolder, title=newFolder)
+		else:
+			errorNo = 102
+		error = """<Error number="%s" originalDescription="%s" />""" % (
+				errorNo,
+				self.convertToXmlAttribute(errorMsg)
+				)
+		return error
+
+	def createNonZopeFolder(self, resourceType, currentFolder):
+		errorNo = 0
+		errorMsg = ""
+		if self.request.has_key("NewFolderName"):
+			newFolder = self.request.get("NewFolderName", None)
+			currentFolderPath = self.serverMapFolder(
+					resourceType,
+					currentFolder
+					)
+			try:
+				newFolderPath = currentFolderPath + newFolder
+				errorMsg = self.createServerFolder(newFolderPath)
+				if (errorMsg is not None):
+					errorNo = 110
+			except:
+				errorNo = 103
+		else:
+			errorNo = 102
+		error = """<Error number="%s" originalDescription="%s" />""" % (
+				errorNo,
+				self.convertToXmlAttribute(errorMsg)
+				)
+		return error
+
+	"""
+	getFileName
+
+	Purpose: helper function to extrapolate the filename
+	"""
+	def getFileName(self, filename):
+		for splitChar in ["/", "\\"]:
+			array = filename.split(splitChar)
+			if (len(array) > 1):
+				filename = array[-1]
+		return filename
+
+	"""
+	fileUpload
+
+	Purpose: command to upload files to server
+	"""
+	def fileUpload(self, resourceType, currentFolder):
+		if (self.isZope()):
+			return self.zopeFileUpload(resourceType, currentFolder)
+		else:
+			return self.nonZopeFileUpload(resourceType, currentFolder)
+
+	def zopeFileUpload(self, resourceType, currentFolder, count=None):
+		zopeFolder = self.findZopeFolder(resourceType, currentFolder)
+		file = self.request.get("NewFile", None)
+		fileName = self.getFileName(file.filename)
+		fileNameOnly = self.removeExtension(fileName)
+		fileExtension = self.getExtension(fileName).lower()
+		if (count):
+			nid = "%s.%s.%s" % (fileNameOnly, count, fileExtension)
+		else:
+			nid = fileName
+		title = nid
+		try:
+			zopeFolder.manage_addProduct['OFSP'].manage_addFile(
+					id=nid,
+					title=title,
+					file=file.read()
+					)
+		except:
+			if (count):
+				count += 1
+			else:
+				count = 1
+			self.zopeFileUpload(resourceType, currentFolder, count)
+		return
+
+	def nonZopeFileUpload(self, resourceType, currentFolder):
+		errorNo = 0
+		errorMsg = ""
+		if self.request.has_key("NewFile"):
+			# newFile has all the contents we need
+			newFile = self.request.get("NewFile", "")
+			# Get the file name
+			newFileName = newFile.filename
+			newFileNameOnly = self.removeExtension(newFileName)
+			newFileExtension = self.getExtension(newFileName).lower()
+			allowedExtensions = self.getAllowedExtensions(resourceType)
+			deniedExtensions = self.getDeniedExtensions(resourceType)
+			if (allowedExtensions is not None):
+				# Check for allowed
+				isAllowed = False
+				if (newFileExtension in allowedExtensions):
+					isAllowed = True
+			elif (deniedExtensions is not None):
+				# Check for denied
+				isAllowed = True
+				if (newFileExtension in deniedExtensions):
+					isAllowed = False
+			else:
+				# No extension limitations
+				isAllowed = True
+
+			if (isAllowed):
+				if (self.isZope()):
+					# Upload into zope
+					self.zopeFileUpload(resourceType, currentFolder)
+				else:
+					# Upload to operating system
+					# Map the virtual path to the local server path
+					currentFolderPath = self.serverMapFolder(
+							resourceType,
+							currentFolder
+							)
+					i = 0
+					while (True):
+						newFilePath = "%s%s" % (
+								currentFolderPath,
+								newFileName
+								)
+						if os.path.exists(newFilePath):
+							i += 1
+							newFilePath = "%s%s(%s).%s" % (
+									currentFolderPath,
+									newFileNameOnly,
+									i,
+									newFileExtension
+									)
+							errorNo = 201
+							break
+						else:
+							fileHandle = open(newFilePath,'w')
+							linecount = 0
+							while (1):
+								#line = newFile.file.readline()
+								line = newFile.readline()
+								if not line: break
+								fileHandle.write("%s" % line)
+								linecount += 1
+							os.chmod(newFilePath, 0777)
+							break
+			else:
+				newFileName = "Extension not allowed"
+				errorNo = 203
+		else:
+			newFileName = "No File"
+			errorNo = 202
+
+		string = """
+<script type="text/javascript">
+window.parent.frames["frmUpload"].OnUploadCompleted(%s,"%s");
+</script>
+				""" % (
+						errorNo,
+						newFileName.replace('"',"'")
+						)
+		return string
+
+	def run(self):
+		s = ""
+		try:
+			# Check if this is disabled
+			if not(self.enabled):
+				return self.sendError(1, "This connector is disabled.  Please check the connector configurations and try again")
+			# Make sure we have valid inputs
+			if not(
+					(self.request.has_key("Command")) and
+					(self.request.has_key("Type")) and
+					(self.request.has_key("CurrentFolder"))
+					):
+				return
+			# Get command
+			command = self.request.get("Command", None)
+			# Get resource type
+			resourceType = self.request.get("Type", None)
+			# folder syntax must start and end with "/"
+			currentFolder = self.request.get("CurrentFolder", None)
+			if (currentFolder[-1] <> "/"):
+				currentFolder += "/"
+			if (currentFolder[0] <> "/"):
+				currentFolder = "/" + currentFolder
+			# Check for invalid paths
+			if (".." in currentFolder):
+				return self.sendError(102, "")
+			# File upload doesn't have to return XML, so intercept
+			# her:e
+			if (command == "FileUpload"):
+				return self.fileUpload(resourceType, currentFolder)
+			# Begin XML
+			s += self.createXmlHeader(command, resourceType, currentFolder)
+			# Execute the command
+			if (command == "GetFolders"):
+				f = self.getFolders
+			elif (command == "GetFoldersAndFiles"):
+				f = self.getFoldersAndFiles
+			elif (command == "CreateFolder"):
+				f = self.createFolder
+			else:
+				f = None
+			if (f is not None):
+				s += f(resourceType, currentFolder)
+			s += self.createXmlFooter()
+		except Exception, e:
+			s = "ERROR: %s" % e
+		return s
+
+# Running from command line
+if __name__ == '__main__':
+	# To test the output, uncomment the standard headers
+	#print "Content-Type: text/html"
+	#print ""
+	print getFCKeditorConnector()
+
+"""
+Running from zope, you will need to modify this connector.
+If you have uploaded the FCKeditor into Zope (like me), you need to
+move this connector out of Zope, and replace the "connector" with an
+alias as below.  The key to it is to pass the Zope context in, as
+we then have a like to the Zope context.
+
+## Script (Python) "connector.py"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=*args, **kws
+##title=ALIAS
+##
+import Products.connector as connector
+return connector.getFCKeditorConnector(context=context).run()
+"""
+
+
Index: /FCKeditor/branches/developers/alfonsoml/fckconfig.js
===================================================================
--- /FCKeditor/branches/developers/alfonsoml/fckconfig.js	(revision 314)
+++ /FCKeditor/branches/developers/alfonsoml/fckconfig.js	(revision 315)
@@ -184,5 +184,5 @@
 // Custom implementations should just ignore it.
 var _FileBrowserLanguage	= 'asp' ;	// asp | aspx | cfm | lasso | perl | php | py
-var _QuickUploadLanguage	= 'asp' ;	// asp | aspx | cfm | lasso | php
+var _QuickUploadLanguage	= 'asp' ;	// asp | aspx | cfm | lasso | perl | php
 
 // @Packager.Remove.Start
