-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFTP_Server.py
More file actions
321 lines (291 loc) · 9.85 KB
/
FTP_Server.py
File metadata and controls
321 lines (291 loc) · 9.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
import socket
import threading
import os
fileLock = threading.Lock()
def isUserNameValid(dataBase,userName):
#Open the DataBase:
file = open(dataBase, 'r')
Data = file.readlines()
file.close()
for user in Data:
registeredUserName,registeredUserPass = user.split()
if userName == registeredUserName:
return True
#End_If
#Enf_For
return False
#End_User Validation
def isUserPassWordValid(dataBase,userName,passWord):
#Open the DataBase:
file = open(dataBase, 'r')
Data = file.readlines()
file.close()
for user in Data:
registeredUserName,registeredUserPass = user.split()
if userName == registeredUserName and passWord==registeredUserPass:
return True
#End_If
#Enf_For
return False
#End_User Validation
def UploadFile(filename,commandSocket,dataPort,clientIP,dataSocket):
bufferSize= 7168 #Define the Buffer Size
print("Server Uploading File..")
#Check if the File Exist before doing anything:
if not os.path.exists(filename):
message = "550 File not found in CurrentDir."
commandSocket.send(message.ecode())
return
#End_if
#Try to Establish Data connection if File Exist:
#dataSocket = socket.socket()
dataConnection,address = dataSocket.accept()
try:
dataConnection.connect((clientIP, dataPort))
message = "225 Data connection open; transfer in progress."
commandSocket.send(message.ecode())
#Now open the File for Transferring:
fileLock.acquire()
with open(filename, 'rb') as theFile:
bytesToSend = theFile.read(bufferSize)
dataConnection.send(bytesToSend)
while bytesToSend != "":
bytesToSend = theFile.read(bufferSize)
dataConnection.send(bytesToSend)
#End_While
#End_With
#Close the File and Dat connection:
theFile.close()
fileLock.release()
message = "226 Transfer completed Closing data connection."
commandSocket.send(message.ecode())
dataConnection.close()
except:
message = "425 Failed to open data connection on ("+clientIP+","+dataPort+")."
print(message)
commandSocket.send(message.ecode())
return
#End_Try_Except
#End_Upload
def DownloadFile(filename,commandSocket,dataPort=20,clientIP='127.0.0.1'):
bufferSize = 7168 #Define the Buffer Size
print("Server Downloading File..")
if os.path.exists(filename): #If the file already Exist deny the fine to avoid overwriting
message = "553 File not name not allowed, try renaming it."
commandSocket.send(message.ecode())
return
else: #otherwise create the file to write to
os.makedirs(filename)
message = "150 File status okay; about to open data connection."
commandSocket.send(message.ecode())
#End_if
#Try to Establish Data connection:
#dataSocket = socket.socket()
dataConnection,address = dataSocket.accept()
try:
dataConnection.connect((clientIP, dataPort))
message = "225 Data connection open; transfer in ready."
commandSocket.send(message.ecode())
#Now open the File for Downloading:
bytesToSave = dataConnection.recv(bufferSize)
theFile = open(filename, 'wb')
while bytesToSave:
theFile.write(bytesToSave)
bytesToSave = dataConnection.recv(bufferSize)
#End_While
#Close the File and Dat connection:
theFile.close()
message = "226 Transfer completed Closing data connection."
commandSocket.send(message.ecode())
dataConnection.close()
except:
message = "425 Failed to open data connection on ("+clientIP+","+dataPort+")."
print(message)
commandSocket.send(message.ecode())
return
#End_Try_Except
#End_Upload
def clientLogIn(clientIP,commandSocket,DataBase):
print("We are loggin in...\n")
request = commandSocket.recv(7168).decode().rstrip() #Expecting a User Name
print(clientIP+" Request: "+request)
command = request.split()
userName = command[-1] #command[1] -> username
if command[0].upper() == "USER": #command[0] -> FTP command
if isUserNameValid(DataBase,userName):
message = "331 Password required to access user account "+userName
commandSocket.send(message.encode())
request = commandSocket.recv(7168).decode().rstrip() #Expecting a User Password
print(clientIP+" Request: "+request)
command = request.split() #command[1] -> userPassword
userPassword = command[-1] #command[1] -> username
if command[0].upper()=="PASS":
if isUserPassWordValid(DataBase,userName,userPassword):
message = "230 Logged in."
commandSocket.send(message.encode())
print("Client Logged in")
return True
else:
message = "502 incorrect password for "+userName
commandSocket.send(message.encode())
return False
#End_if
else:
message = "502 Command "+command[0]+" not implemented."
commandSocket.send(message.encode())
return False
else:
message = "332 UserName "+userName+" not registered. Need account for log in"
commandSocket.send(message.encode())
return False
#End_Else
else:
message = "502 Command "+command[0]+"not implemented."
commandSocket.send(message.encode())
return False
#End_LogIn
def ftp_LIST(directory):
valid = os.path.isdir(directory) #Check if the specified Directory exist
if valid:
items = os.listdir(directory) #get a list of all the items in the specified directory
response = "200 "+ " ".join(items) #Join the item list into a space seperated string
return response
else:
response = "450 directory '"+directory+"' not found."
return response
#end if
#End_LIST
def ftp_CWD(requestedDir,HomeDir, CurrentDir):
#Check if the request Directory Exist in the Current directory
temp = CurrentDir+requestedDir
valid = os.path.isdir(temp)
if valid:
newDirectory = temp
response = "200 CWD changed to "+newDirectory
return (response,newDirectory)
else:#Check if the request Directory Exist in the Home directory
temp = HomeDir+requestedDir
valid = os.path.isdir(temp)
if valid:
newDirectory = temp
response = "200 CWD changed to "+newDirectory
return (response,newDirectory)
else:
newDirectory = CurrentDir
response = "450 requested Dir not found in Current nor Home Dir"
return (response,newDirectory)
#End_if
#End_if
#End_CWD
def ftp_PWD(homeDir,currDir):
lastFolder = homeDir.split('\\')
lastFolder = lastFolder[-1]
if currDir.find(homeDir) != -1:
currDir = currDir.replace(homeDir,'')
response = "200 Current working dir is \\"+lastFolder+currDir
return response
else:
return "200 Current working dir is \\"+lastFolder
#End_PWD
def syntexError():
return "501 Syntax error in parameters or arguments."
def ClientHandler(DataBase,clientIP,commandSocket,dataSocket):
bufferSize = 7168
#Set the Current Directory for the Client
HomeDirectory = os.getcwd()
WorkingDirectory = os.getcwd()
print("Home dir= "+HomeDirectory)
print("Current dir= "+WorkingDirectory)
#Send the Hello Message:
message = "220 Hello, this is the Nchabeleng File Service."
commandSocket.send(message.encode())
#User Validation Process:
loggedin = False
while not loggedin:
loggedin = clientLogIn(clientIP,commandSocket,DataBase)
#End_Log in
#Interaction Client
while True:
try:
request = commandSocket.recv(bufferSize).decode().rstrip()
command = request.split()
print(clientIP+" "+request)
ftpCommand = command[0]
ftpData = command[-1]
print("ftp C= "+ftpCommand)
print("ftp D= "+ftpData)
#commandSocket.send(".".encode())
if ftpCommand=="QUIT":
message = "221 Goodbye."
commandSocket.send(message.encode())
break
elif ftpCommand=="STOR":
if ftpCommand==ftpData:
message = syntexError()
commandSocket.send(message.encode())
else:
path = WorkingDirectory+ftpData
DownloadFile(path,commandSocket,dataSocket)
elif ftpCommand=="RETR":
print("we are here..")
if ftpCommand==ftpData:
message = syntexError()
commandSocket.send(message.encode())
else:
print("then here..")
path = WorkingDirectory+ftpData
UPloadFile(path,commandSocket,dataSocket)
print("then finally here...")
elif ftpCommand=="CWD":
if ftpCommand==ftpData:
message = syntexError()
commandSocket.send(message.encode())
else:
message,WorkingDirectory = ftp_CWD(ftpData,HomeDirectory,WorkingDirectory)
commandSocket.send(message.encode())
elif ftpCommand=="PWD":
message = ftp_PWD(HomeDirectory,WorkingDirectory)
commandSocket.send(message.encode())
elif ftpCommand=="LIST":
message = ftp_LIST(WorkingDirectory)
commandSocket.send(message.encode())
elif ftpCommand=="CDUP":
WorkingDirectory = HomeDirectory
message = ftp_PWD(HomeDirectory,WorkingDirectory)
commandSocket.send(message.encode())
elif ftpCommand=="NOOP":
message = "200 Okay "+clientIP
commandSocket.send(message.encode())
else:
message = "502 Command "+ftpCommand+" not implemented."
commandSocket.send(message.encode())
#End if:
except: #If fail to receive then the conncection has been closed
print("Command Socket is Closed.")
break
#End_While_Interaction
print("Done servicing Client "+clientIP)
#commandSocket.close()
#End_ClientHanlder
def Main():
host = '127.0.0.1'
commadPort = 21
dataPort = 20
commandSocket = socket.socket()
commandSocket.bind((host,commadPort))
commandSocket.listen(5)
dataSocket = socket.socket()
dataSocket.bind((host,dataPort))
commandSocket.listen(5)
print("Server Started.")
while True:
clientSocket, clientAddr = commandSocket.accept()
print("client connected ip:<" + str(clientAddr) + ">")
t = threading.Thread(target=ClientHandler, args=("dataBase.txt",str(clientAddr),clientSocket,dataSocket))
#ClientHandler(DataBase,clientIP,commandSocket,dataSocket)
t.start()
#End_While
print("Server Down")
commandSocket.close()
if __name__ == '__main__':
Main()