connector.py
上传用户:li2971742
上传日期:2021-11-18
资源大小:39096k
文件大小:22k
源码类别:

OA系统

开发平台:

C#

  1. #!/usr/bin/env python
  2. """
  3. FCKeditor - The text editor for internet
  4. Copyright (C) 2003-2006 Frederico Caldeira Knabben
  5. Licensed under the terms of the GNU Lesser General Public License:
  6. http://www.opensource.org/licenses/lgpl-license.php
  7. For further information visit:
  8. http://www.fckeditor.net/
  9. "Support Open Source software. What about a donation today?"
  10. File Name: connector.py
  11. Connector for Python.
  12. Tested With:
  13. Standard:
  14. Python 2.3.3
  15. Zope:
  16. Zope Version: (Zope 2.8.1-final, python 2.3.5, linux2)
  17. Python Version: 2.3.5 (#4, Mar 10 2005, 01:40:25) 
  18. [GCC 3.3.3 20040412 (Red Hat Linux 3.3.3-7)]
  19. System Platform: linux2 
  20. File Authors:
  21. Andrew Liu (andrew@liuholdings.com)
  22. """
  23. """
  24. Author Notes (04 December 2005):
  25. This module has gone through quite a few phases of change.  Obviously,
  26. I am only supporting that part of the code that I use.  Initially
  27. I had the upload directory as a part of zope (ie. uploading files
  28. directly into Zope), before realising that there were too many 
  29. complex intricacies within Zope to deal with.  Zope is one ugly piece
  30. of code.  So I decided to complement Zope by an Apache server (which
  31. I had running anyway, and doing nothing).  So I mapped all uploads
  32. from an arbitrary server directory to an arbitrary web directory.
  33. All the FCKeditor uploading occurred this way, and I didn't have to
  34. stuff around with fiddling with Zope objects and the like (which are
  35. terribly complex and something you don't want to do - trust me).
  36. Maybe a Zope expert can touch up the Zope components.  In the end, 
  37. I had FCKeditor loaded in Zope (probably a bad idea as well), and
  38. I replaced the connector.py with an alias to a server module.
  39. Right now, all Zope components will simple remain as is because
  40. I've had enough of Zope.
  41. See notes right at the end of this file for how I aliased out of Zope.
  42. Anyway, most of you probably wont use Zope, so things are pretty
  43. simple in that regard.
  44. Typically, SERVER_DIR is the root of WEB_DIR (not necessarily).
  45. Most definitely, SERVER_USERFILES_DIR points to WEB_USERFILES_DIR.
  46. """
  47. import cgi
  48. import re
  49. import os
  50. import string
  51. """
  52. escape
  53. Converts the special characters '<', '>', and '&'.
  54. RFC 1866 specifies that these characters be represented
  55. in HTML as &lt; &gt; and &amp; respectively. In Python
  56. 1.5 we use the new string.replace() function for speed.
  57. """
  58. def escape(text, replace=string.replace):
  59.     text = replace(text, '&', '&amp;') # must be done 1st
  60.     text = replace(text, '<', '&lt;')
  61.     text = replace(text, '>', '&gt;')
  62.     text = replace(text, '"', '&quot;')
  63.     return text
  64. """
  65. getFCKeditorConnector
  66. Creates a new instance of an FCKeditorConnector, and runs it
  67. """
  68. def getFCKeditorConnector(context=None):
  69. # Called from Zope.  Passes the context through
  70. connector = FCKeditorConnector(context=context)
  71. return connector.run()
  72. """
  73. FCKeditorRequest
  74. A wrapper around the request object
  75. Can handle normal CGI request, or a Zope request
  76. Extend as required
  77. """
  78. class FCKeditorRequest(object):
  79. def __init__(self, context=None):
  80. if (context is not None):
  81. r = context.REQUEST
  82. else:
  83. r = cgi.FieldStorage()
  84. self.context = context
  85. self.request = r
  86. def isZope(self):
  87. if (self.context is not None):
  88. return True
  89. return False
  90. def has_key(self, key):
  91. return self.request.has_key(key)
  92. def get(self, key, default=None):
  93. value = None
  94. if (self.isZope()):
  95. value = self.request.get(key, default)
  96. else:
  97. if key in self.request.keys():
  98. value = self.request[key].value
  99. else:
  100. value = default
  101. return value
  102. """
  103. FCKeditorConnector
  104. The connector class
  105. """
  106. class FCKeditorConnector(object):
  107. # Configuration for FCKEditor
  108. # can point to another server here, if linked correctly
  109. #WEB_HOST = "http://127.0.0.1/" 
  110. WEB_HOST = ""
  111. SERVER_DIR = "/var/www/html/"
  112. WEB_USERFILES_FOLDER = WEB_HOST + "upload/"
  113. SERVER_USERFILES_FOLDER = SERVER_DIR + "upload/"
  114. # Allow access (Zope)
  115. __allow_access_to_unprotected_subobjects__ = 1
  116. # Class Attributes
  117. parentFolderRe = re.compile("[/][^/]+[/]?$")
  118. """
  119. Constructor
  120. """
  121. def __init__(self, context=None):
  122. # The given root path will NOT be shown to the user
  123. # Only the userFilesPath will be shown
  124. # Instance Attributes
  125. self.context = context
  126. self.request = FCKeditorRequest(context=context)
  127. self.rootPath = self.SERVER_DIR
  128. self.userFilesFolder = self.SERVER_USERFILES_FOLDER
  129. self.webUserFilesFolder = self.WEB_USERFILES_FOLDER
  130. # Enables / Disables the connector
  131. self.enabled = False # Set to True to enable this connector
  132. # These are instance variables
  133. self.zopeRootContext = None
  134. self.zopeUploadContext = None
  135. # Copied from php module =)
  136. self.allowedExtensions = {
  137. "File": None,
  138. "Image": None,
  139. "Flash": None,
  140. "Media": None
  141. }
  142. self.deniedExtensions = {
  143. "File": [ "php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess" ],
  144. "Image": [ "php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess" ],
  145. "Flash": [ "php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess" ],
  146. "Media": [ "php","php2","php3","php4","php5","phtml","pwml","inc","asp","aspx","ascx","jsp","cfm","cfc","pl","bat","exe","com","dll","vbs","js","reg","cgi","htaccess" ]
  147. }
  148. """
  149. Zope specific functions
  150. """
  151. def isZope(self):
  152. # The context object is the zope object
  153. if (self.context is not None):
  154. return True
  155. return False
  156. def getZopeRootContext(self):
  157. if self.zopeRootContext is None:
  158. self.zopeRootContext = self.context.getPhysicalRoot()
  159. return self.zopeRootContext
  160. def getZopeUploadContext(self):
  161. if self.zopeUploadContext is None:
  162. folderNames = self.userFilesFolder.split("/")
  163. c = self.getZopeRootContext()
  164. for folderName in folderNames:
  165. if (folderName <> ""):
  166. c = c[folderName]
  167. self.zopeUploadContext = c
  168. return self.zopeUploadContext
  169. """
  170. Generic manipulation functions
  171. """
  172. def getUserFilesFolder(self):
  173. return self.userFilesFolder
  174. def getWebUserFilesFolder(self):
  175. return self.webUserFilesFolder
  176. def getAllowedExtensions(self, resourceType):
  177. return self.allowedExtensions[resourceType]
  178. def getDeniedExtensions(self, resourceType):
  179. return self.deniedExtensions[resourceType]
  180. def removeFromStart(self, string, char):
  181. return string.lstrip(char)
  182. def removeFromEnd(self, string, char):
  183. return string.rstrip(char)
  184. def convertToXmlAttribute(self, value):
  185. if (value is None):
  186. value = ""
  187. return escape(value)
  188. def convertToPath(self, path):
  189. if (path[-1] <> "/"):
  190. return path + "/"
  191. else:
  192. return path
  193. def getUrlFromPath(self, resourceType, path):
  194. if (resourceType is None) or (resourceType == ''):
  195. url = "%s%s" % (
  196. self.removeFromEnd(self.getUserFilesFolder(), '/'),
  197. path
  198. )
  199. else:
  200. url = "%s%s%s" % (
  201. self.getUserFilesFolder(),
  202. resourceType,
  203. path
  204. )
  205. return url
  206. def getWebUrlFromPath(self, resourceType, path):
  207. if (resourceType is None) or (resourceType == ''):
  208. url = "%s%s" % (
  209. self.removeFromEnd(self.getWebUserFilesFolder(), '/'),
  210. path
  211. )
  212. else:
  213. url = "%s%s%s" % (
  214. self.getWebUserFilesFolder(),
  215. resourceType,
  216. path
  217. )
  218. return url
  219. def removeExtension(self, fileName):
  220. index = fileName.rindex(".")
  221. newFileName = fileName[0:index]
  222. return newFileName
  223. def getExtension(self, fileName):
  224. index = fileName.rindex(".") + 1
  225. fileExtension = fileName[index:]
  226. return fileExtension
  227. def getParentFolder(self, folderPath):
  228. parentFolderPath = self.parentFolderRe.sub('', folderPath)
  229. return parentFolderPath
  230. """
  231. serverMapFolder
  232. Purpose: works out the folder map on the server
  233. """
  234. def serverMapFolder(self, resourceType, folderPath):
  235. # Get the resource type directory
  236. resourceTypeFolder = "%s%s/" % (
  237. self.getUserFilesFolder(),
  238. resourceType
  239. )
  240. # Ensure that the directory exists
  241. self.createServerFolder(resourceTypeFolder)
  242. # Return the resource type directory combined with the
  243. # required path
  244. return "%s%s" % (
  245. resourceTypeFolder,
  246. self.removeFromStart(folderPath, '/')
  247. )
  248. """
  249. createServerFolder
  250. Purpose: physically creates a folder on the server
  251. """
  252. def createServerFolder(self, folderPath):
  253. # Check if the parent exists
  254. parentFolderPath = self.getParentFolder(folderPath)
  255. if not(os.path.exists(parentFolderPath)):
  256. errorMsg = self.createServerFolder(parentFolderPath)
  257. if errorMsg is not None:
  258. return errorMsg
  259. # Check if this exists
  260. if not(os.path.exists(folderPath)):
  261. os.mkdir(folderPath)
  262. os.chmod(folderPath, 0755)
  263. errorMsg = None
  264. else:
  265. if os.path.isdir(folderPath):
  266. errorMsg = None
  267. else:
  268. raise "createServerFolder: Non-folder of same name already exists"
  269. return errorMsg
  270. """
  271. getRootPath
  272. Purpose: returns the root path on the server
  273. """
  274. def getRootPath(self):
  275. return self.rootPath
  276. """
  277. setXmlHeaders
  278. Purpose: to prepare the headers for the xml to return
  279. """
  280. def setXmlHeaders(self):
  281. #now = self.context.BS_get_now()
  282. #yesterday = now - 1
  283. self.setHeader("Content-Type", "text/xml")
  284. #self.setHeader("Expires", yesterday)
  285. #self.setHeader("Last-Modified", now)
  286. #self.setHeader("Cache-Control", "no-store, no-cache, must-revalidate")
  287. self.printHeaders()
  288. return
  289. def setHeader(self, key, value):
  290. if (self.isZope()):
  291. self.context.REQUEST.RESPONSE.setHeader(key, value)
  292. else:
  293. print "%s: %s" % (key, value)
  294. return
  295. def printHeaders(self):
  296. # For non-Zope requests, we need to print an empty line
  297. # to denote the end of headers
  298. if (not(self.isZope())):
  299. print ""
  300. """
  301. createXmlFooter
  302. Purpose: returns the xml header
  303. """
  304. def createXmlHeader(self, command, resourceType, currentFolder):
  305. self.setXmlHeaders()
  306. s = ""
  307. # Create the XML document header
  308. s += """<?xml version="1.0" encoding="utf-8" ?>"""
  309. # Create the main connector node
  310. s += """<Connector command="%s" resourceType="%s">""" % (
  311. command,
  312. resourceType
  313. )
  314. # Add the current folder node
  315. s += """<CurrentFolder path="%s" url="%s" />""" % (
  316. self.convertToXmlAttribute(currentFolder),
  317. self.convertToXmlAttribute(
  318. self.getWebUrlFromPath(
  319. resourceType, 
  320. currentFolder
  321. )
  322. ),
  323. )
  324. return s
  325. """
  326. createXmlFooter
  327. Purpose: returns the xml footer
  328. """
  329. def createXmlFooter(self):
  330. s = """</Connector>"""
  331. return s
  332. """
  333. sendError
  334. Purpose: in the event of an error, return an xml based error
  335. """
  336. def sendError(self, number, text):
  337. self.setXmlHeaders()
  338. s = ""
  339. # Create the XML document header
  340. s += """<?xml version="1.0" encoding="utf-8" ?>"""
  341. s += """<Connector>"""
  342. s += """<Error number="%s" text="%s" />""" % (number, text)
  343. s += """</Connector>"""
  344. return s
  345. """
  346. getFolders
  347. Purpose: command to recieve a list of folders
  348. """
  349. def getFolders(self, resourceType, currentFolder):
  350. if (self.isZope()):
  351. return self.getZopeFolders(resourceType, currentFolder)
  352. else:
  353. return self.getNonZopeFolders(resourceType, currentFolder)
  354. def getZopeFolders(self, resourceType, currentFolder):
  355. # Open the folders node
  356. s = ""
  357. s += """<Folders>"""
  358. zopeFolder = self.findZopeFolder(resourceType, currentFolder)
  359. for (name, o) in zopeFolder.objectItems(["Folder"]):
  360. s += """<Folder name="%s" />""" % (
  361. self.convertToXmlAttribute(name)
  362. )
  363. # Close the folders node
  364. s += """</Folders>"""
  365. return s
  366. def getNonZopeFolders(self, resourceType, currentFolder):
  367. # Map the virtual path to our local server
  368. serverPath = self.serverMapFolder(resourceType, currentFolder)
  369. # Open the folders node
  370. s = ""
  371. s += """<Folders>"""
  372. for someObject in os.listdir(serverPath):
  373. someObjectPath = os.path.join(serverPath, someObject)
  374. if os.path.isdir(someObjectPath):
  375. s += """<Folder name="%s" />""" % (
  376. self.convertToXmlAttribute(someObject)
  377. )
  378. # Close the folders node
  379. s += """</Folders>"""
  380. return s
  381. """
  382. getFoldersAndFiles
  383. Purpose: command to recieve a list of folders and files
  384. """
  385. def getFoldersAndFiles(self, resourceType, currentFolder):
  386. if (self.isZope()):
  387. return self.getZopeFoldersAndFiles(resourceType, currentFolder)
  388. else:
  389. return self.getNonZopeFoldersAndFiles(resourceType, currentFolder)
  390. def getNonZopeFoldersAndFiles(self, resourceType, currentFolder):
  391. # Map the virtual path to our local server
  392. serverPath = self.serverMapFolder(resourceType, currentFolder)
  393. # Open the folders / files node
  394. folders = """<Folders>"""
  395. files = """<Files>"""
  396. for someObject in os.listdir(serverPath):
  397. someObjectPath = os.path.join(serverPath, someObject)
  398. if os.path.isdir(someObjectPath):
  399. folders += """<Folder name="%s" />""" % (
  400. self.convertToXmlAttribute(someObject)
  401. )
  402. elif os.path.isfile(someObjectPath):
  403. size = os.path.getsize(someObjectPath)
  404. files += """<File name="%s" size="%s" />""" % (
  405. self.convertToXmlAttribute(someObject),
  406. os.path.getsize(someObjectPath)
  407. )
  408. # Close the folders / files node
  409. folders += """</Folders>"""
  410. files += """</Files>"""
  411. # Return it
  412. s = folders + files
  413. return s
  414. def getZopeFoldersAndFiles(self, resourceType, currentFolder):
  415. folders = self.getZopeFolders(resourceType, currentFolder)
  416. files = self.getZopeFiles(resourceType, currentFolder)
  417. s = folders + files
  418. return s
  419. def getZopeFiles(self, resourceType, currentFolder):
  420. # Open the files node
  421. s = ""
  422. s += """<Files>"""
  423. zopeFolder = self.findZopeFolder(resourceType, currentFolder)
  424. for (name, o) in zopeFolder.objectItems(["File","Image"]):
  425. s += """<File name="%s" size="%s" />""" % (
  426. self.convertToXmlAttribute(name),
  427. ((o.get_size() / 1024) + 1)
  428. )
  429. # Close the files node
  430. s += """</Files>"""
  431. return s
  432. def findZopeFolder(self, resourceType, folderName):
  433. # returns the context of the resource / folder
  434. zopeFolder = self.getZopeUploadContext()
  435. folderName = self.removeFromStart(folderName, "/")
  436. folderName = self.removeFromEnd(folderName, "/")
  437. if (resourceType <> ""):
  438. try:
  439. zopeFolder = zopeFolder[resourceType]
  440. except:
  441. zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=resourceType, title=resourceType)
  442. zopeFolder = zopeFolder[resourceType]
  443. if (folderName <> ""):
  444. folderNames = folderName.split("/")
  445. for folderName in folderNames:
  446. zopeFolder = zopeFolder[folderName]
  447. return zopeFolder
  448. """
  449. createFolder
  450. Purpose: command to create a new folder
  451. """
  452. def createFolder(self, resourceType, currentFolder):
  453. if (self.isZope()):
  454. return self.createZopeFolder(resourceType, currentFolder)
  455. else:
  456. return self.createNonZopeFolder(resourceType, currentFolder)
  457. def createZopeFolder(self, resourceType, currentFolder):
  458. # Find out where we are
  459. zopeFolder = self.findZopeFolder(resourceType, currentFolder)
  460. errorNo = 0
  461. errorMsg = ""
  462. if self.request.has_key("NewFolderName"):
  463. newFolder = self.request.get("NewFolderName", None)
  464. zopeFolder.manage_addProduct["OFSP"].manage_addFolder(id=newFolder, title=newFolder)
  465. else:
  466. errorNo = 102
  467. error = """<Error number="%s" originalDescription="%s" />""" % (
  468. errorNo,
  469. self.convertToXmlAttribute(errorMsg)
  470. )
  471. return error
  472. def createNonZopeFolder(self, resourceType, currentFolder):
  473. errorNo = 0
  474. errorMsg = ""
  475. if self.request.has_key("NewFolderName"):
  476. newFolder = self.request.get("NewFolderName", None)
  477. currentFolderPath = self.serverMapFolder(
  478. resourceType, 
  479. currentFolder
  480. )
  481. try:
  482. newFolderPath = currentFolderPath + newFolder
  483. errorMsg = self.createServerFolder(newFolderPath)
  484. if (errorMsg is not None):
  485. errorNo = 110
  486. except:
  487. errorNo = 103
  488. else:
  489. errorNo = 102
  490. error = """<Error number="%s" originalDescription="%s" />""" % (
  491. errorNo,
  492. self.convertToXmlAttribute(errorMsg)
  493. )
  494. return error
  495. """
  496. getFileName
  497. Purpose: helper function to extrapolate the filename
  498. """
  499. def getFileName(self, filename):
  500. for splitChar in ["/", "\"]:
  501. array = filename.split(splitChar)
  502. if (len(array) > 1):
  503. filename = array[-1]
  504. return filename
  505. """
  506. fileUpload
  507. Purpose: command to upload files to server
  508. """
  509. def fileUpload(self, resourceType, currentFolder):
  510. if (self.isZope()):
  511. return self.zopeFileUpload(resourceType, currentFolder)
  512. else:
  513. return self.nonZopeFileUpload(resourceType, currentFolder)
  514. def zopeFileUpload(self, resourceType, currentFolder, count=None):
  515. zopeFolder = self.findZopeFolder(resourceType, currentFolder)
  516. file = self.request.get("NewFile", None)
  517. fileName = self.getFileName(file.filename)
  518. fileNameOnly = self.removeExtension(fileName)
  519. fileExtension = self.getExtension(fileName).lower()
  520. if (count):
  521. nid = "%s.%s.%s" % (fileNameOnly, count, fileExtension)
  522. else:
  523. nid = fileName
  524. title = nid
  525. try:
  526. zopeFolder.manage_addProduct['OFSP'].manage_addFile(
  527. id=nid,
  528. title=title,
  529. file=file.read()
  530. )
  531. except:
  532. if (count):
  533. count += 1
  534. else:
  535. count = 1
  536. self.zopeFileUpload(resourceType, currentFolder, count)
  537. return
  538. def nonZopeFileUpload(self, resourceType, currentFolder):
  539. errorNo = 0
  540. errorMsg = ""
  541. if self.request.has_key("NewFile"):
  542. # newFile has all the contents we need
  543. newFile = self.request.get("NewFile", "")
  544. # Get the file name
  545. newFileName = newFile.filename
  546. newFileNameOnly = self.removeExtension(newFileName)
  547. newFileExtension = self.getExtension(newFileName).lower()
  548. allowedExtensions = self.getAllowedExtensions(resourceType)
  549. deniedExtensions = self.getDeniedExtensions(resourceType)
  550. if (allowedExtensions is not None):
  551. # Check for allowed
  552. isAllowed = False
  553. if (newFileExtension in allowedExtensions):
  554. isAllowed = True
  555. elif (deniedExtensions is not None):
  556. # Check for denied
  557. isAllowed = True
  558. if (newFileExtension in deniedExtensions):
  559. isAllowed = False
  560. else:
  561. # No extension limitations
  562. isAllowed = True
  563. if (isAllowed):
  564. if (self.isZope()):
  565. # Upload into zope
  566. self.zopeFileUpload(resourceType, currentFolder)
  567. else:
  568. # Upload to operating system
  569. # Map the virtual path to the local server path
  570. currentFolderPath = self.serverMapFolder(
  571. resourceType, 
  572. currentFolder
  573. )
  574. i = 0
  575. while (True):
  576. newFilePath = "%s%s" % (
  577. currentFolderPath,
  578. newFileName
  579. )
  580. if os.path.exists(newFilePath):
  581. i += 1
  582. newFilePath = "%s%s(%s).%s" % (
  583. currentFolderPath,
  584. newFileNameOnly,
  585. i,
  586. newFileExtension
  587. )
  588. errorNo = 201
  589. break
  590. else:
  591. fileHandle = open(newFilePath,'w')
  592. linecount = 0
  593. while (1):
  594. #line = newFile.file.readline()
  595. line = newFile.readline()
  596. if not line: break
  597. fileHandle.write("%s" % line)
  598. linecount += 1
  599. os.chmod(newFilePath, 0777)
  600. break
  601. else:
  602. newFileName = "Extension not allowed"
  603. errorNo = 203
  604. else:
  605. newFileName = "No File"
  606. errorNo = 202
  607. string = """
  608. <script type="text/javascript">
  609. window.parent.frames["frmUpload"].OnUploadCompleted(%s,"%s");
  610. </script>
  611. """ % (
  612. errorNo,
  613. newFileName.replace('"',"'")
  614. )
  615. return string
  616. def run(self):
  617. s = ""
  618. try:
  619. # Check if this is disabled
  620. if not(self.enabled):
  621. return self.sendError(1, "This connector is disabled.  Please check the connector configurations and try again")
  622. # Make sure we have valid inputs
  623. if not(
  624. (self.request.has_key("Command")) and 
  625. (self.request.has_key("Type")) and 
  626. (self.request.has_key("CurrentFolder"))
  627. ):
  628. return 
  629. # Get command
  630. command = self.request.get("Command", None)
  631. # Get resource type
  632. resourceType = self.request.get("Type", None)
  633. # folder syntax must start and end with "/"
  634. currentFolder = self.request.get("CurrentFolder", None)
  635. if (currentFolder[-1] <> "/"):
  636. currentFolder += "/"
  637. if (currentFolder[0] <> "/"):
  638. currentFolder = "/" + currentFolder
  639. # Check for invalid paths
  640. if (".." in currentFolder):
  641. return self.sendError(102, "")
  642. # File upload doesn't have to return XML, so intercept
  643. # her:e
  644. if (command == "FileUpload"):
  645. return self.fileUpload(resourceType, currentFolder)
  646. # Begin XML
  647. s += self.createXmlHeader(command, resourceType, currentFolder)
  648. # Execute the command
  649. if (command == "GetFolders"):
  650. f = self.getFolders
  651. elif (command == "GetFoldersAndFiles"):
  652. f = self.getFoldersAndFiles
  653. elif (command == "CreateFolder"):
  654. f = self.createFolder
  655. else:
  656. f = None
  657. if (f is not None):
  658. s += f(resourceType, currentFolder)
  659. s += self.createXmlFooter()
  660. except Exception, e:
  661. s = "ERROR: %s" % e
  662. return s
  663. # Running from command line
  664. if __name__ == '__main__':
  665. # To test the output, uncomment the standard headers
  666. #print "Content-Type: text/html"
  667. #print ""
  668. print getFCKeditorConnector()
  669. """
  670. Running from zope, you will need to modify this connector. 
  671. If you have uploaded the FCKeditor into Zope (like me), you need to 
  672. move this connector out of Zope, and replace the "connector" with an
  673. alias as below.  The key to it is to pass the Zope context in, as
  674. we then have a like to the Zope context.
  675. ## Script (Python) "connector.py"
  676. ##bind container=container
  677. ##bind context=context
  678. ##bind namespace=
  679. ##bind script=script
  680. ##bind subpath=traverse_subpath
  681. ##parameters=*args, **kws
  682. ##title=ALIAS
  683. ##
  684. import Products.connector as connector
  685. return connector.getFCKeditorConnector(context=context).run()
  686. """