1#!/usr/bin/env python
2
3"""
4FCKeditor - The text editor for Internet - http://www.fckeditor.net
5Copyright (C) 2003-2007 Frederico Caldeira Knabben
6
7== BEGIN LICENSE ==
8
9Licensed under the terms of any of the following licenses at your
10choice:
11
12- GNU General Public License Version 2 or later (the "GPL")
13http://www.gnu.org/licenses/gpl.html
14
15- GNU Lesser General Public License Version 2.1 or later (the "LGPL")
16http://www.gnu.org/licenses/lgpl.html
17
18- Mozilla Public License Version 1.1 or later (the "MPL")
19http://www.mozilla.org/MPL/MPL-1.1.html
20
21== END LICENSE ==
22
23Connector for Python (CGI and WSGI).
24
25"""
26
27import os
28try: # Windows needs stdio set for binary mode for file upload to work.
29	import msvcrt
30	msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
31	msvcrt.setmode (1, os.O_BINARY) # stdout = 1
32except ImportError:
33	pass
34
35from fckutil import *
36from fckoutput import *
37import config as Config
38
39class GetFoldersCommandMixin (object):
40	def getFolders(self, resourceType, currentFolder):
41		"""
42		Purpose: command to recieve a list of folders
43		"""
44		# Map the virtual path to our local server
45		serverPath = mapServerFolder(self.userFilesFolder,currentFolder)
46		s = """<Folders>"""	 # Open the folders node
47		for someObject in os.listdir(serverPath):
48			someObjectPath = mapServerFolder(serverPath, someObject)
49			if os.path.isdir(someObjectPath):
50				s += """<Folder name="%s" />""" % (
51						convertToXmlAttribute(someObject)
52						)
53		s += """</Folders>""" # Close the folders node
54		return s
55
56class GetFoldersAndFilesCommandMixin (object):
57	def getFoldersAndFiles(self, resourceType, currentFolder):
58		"""
59		Purpose: command to recieve a list of folders and files
60		"""
61		# Map the virtual path to our local server
62		serverPath = mapServerFolder(self.userFilesFolder,currentFolder)
63		# Open the folders / files node
64		folders = """<Folders>"""
65		files = """<Files>"""
66		for someObject in os.listdir(serverPath):
67			someObjectPath = mapServerFolder(serverPath, someObject)
68			if os.path.isdir(someObjectPath):
69				folders += """<Folder name="%s" />""" % (
70						convertToXmlAttribute(someObject)
71						)
72			elif os.path.isfile(someObjectPath):
73				size = os.path.getsize(someObjectPath)
74				files += """<File name="%s" size="%s" />""" % (
75						convertToXmlAttribute(someObject),
76						os.path.getsize(someObjectPath)
77						)
78		# Close the folders / files node
79		folders += """</Folders>"""
80		files += """</Files>"""
81		return folders + files
82
83class CreateFolderCommandMixin (object):
84	def createFolder(self, resourceType, currentFolder):
85		"""
86		Purpose: command to create a new folder
87		"""
88		errorNo = 0; errorMsg ='';
89		if self.request.has_key("NewFolderName"):
90			newFolder = self.request.get("NewFolderName", None)
91			newFolder = sanitizeFolderName (newFolder)
92			try:
93				newFolderPath = mapServerFolder(self.userFilesFolder, combinePaths(currentFolder, newFolder))
94				self.createServerFolder(newFolderPath)
95			except Exception, e:
96				errorMsg = str(e).decode('iso-8859-1').encode('utf-8') # warning with encodigns!!!
97				if hasattr(e,'errno'):
98					if e.errno==17: #file already exists
99						errorNo=0
100					elif e.errno==13: # permission denied
101						errorNo = 103
102					elif e.errno==36 or e.errno==2 or e.errno==22: # filename too long / no such file / invalid name
103						errorNo = 102
104				else:
105					errorNo = 110
106		else:
107			errorNo = 102
108		return self.sendErrorNode ( errorNo, errorMsg )
109
110	def createServerFolder(self, folderPath):
111		"Purpose: physically creates a folder on the server"
112		# No need to check if the parent exists, just create all hierachy
113		oldumask = os.umask(0)
114		os.makedirs(folderPath,mode=0755)
115		os.umask( oldumask )
116
117class UploadFileCommandMixin (object):
118	def uploadFile(self, resourceType, currentFolder):
119		"""
120		Purpose: command to upload files to server (same as FileUpload)
121		"""
122		errorNo = 0
123		if self.request.has_key("NewFile"):
124			# newFile has all the contents we need
125			newFile = self.request.get("NewFile", "")
126			# Get the file name
127			newFileName = newFile.filename
128			newFileName = sanitizeFileName( newFileName )
129			newFileNameOnly = removeExtension(newFileName)
130			newFileExtension = getExtension(newFileName).lower()
131			allowedExtensions = Config.AllowedExtensions[resourceType]
132			deniedExtensions = Config.DeniedExtensions[resourceType]
133
134			if (allowedExtensions):
135				# Check for allowed
136				isAllowed = False
137				if (newFileExtension in allowedExtensions):
138					isAllowed = True
139			elif (deniedExtensions):
140				# Check for denied
141				isAllowed = True
142				if (newFileExtension in deniedExtensions):
143					isAllowed = False
144			else:
145				# No extension limitations
146				isAllowed = True
147
148			if (isAllowed):
149				# Upload to operating system
150				# Map the virtual path to the local server path
151				currentFolderPath = mapServerFolder(self.userFilesFolder, currentFolder)
152				i = 0
153				while (True):
154					newFilePath = os.path.join (currentFolderPath,newFileName)
155					if os.path.exists(newFilePath):
156						i += 1
157						newFileName = "%s(%04d).%s" % (
158								newFileNameOnly, i, newFileExtension
159								)
160						errorNo= 201 # file renamed
161					else:
162						# Read file contents and write to the desired path (similar to php's move_uploaded_file)
163						fout = file(newFilePath, 'wb')
164						while (True):
165							chunk = newFile.file.read(100000)
166							if not chunk: break
167							fout.write (chunk)
168						fout.close()
169
170						if os.path.exists ( newFilePath ):
171							oldumask = os.umask(0)
172							os.chmod( newFilePath, 0755 )
173							os.umask( oldumask )
174
175						newFileUrl = self.webUserFilesFolder + currentFolder + newFileName
176
177						return self.sendUploadResults( errorNo , newFileUrl, newFileName )
178			else:
179				return self.sendUploadResults( errorNo = 203, customMsg = "Extension not allowed" )
180		else:
181			return self.sendUploadResults( errorNo = 202, customMsg = "No File" )
182