1 /********************************************************************************
2 * Nepenthes
3 * - finest collection -
4 *
5 *
6 *
7 * Copyright (C) 2005 Paul Baecher & Markus Koetter
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *
24 * contact nepenthesdev@users.sourceforge.net
25 *
26 *******************************************************************************/
27
28 /* $Id: VFSCommandFTP.cpp 1410 2007-10-12 13:07:23Z common $ */
29
30 #include <cctype>
31 #include <cstring>
32
33 #include "VFSCommandFTP.hpp"
34 #include "VFSNode.hpp"
35 #include "VFSDir.hpp"
36 #include "VFSFile.hpp"
37 #include "Nepenthes.hpp"
38 #include "LogManager.hpp"
39 #include "VFS.hpp"
40 #include "DownloadManager.hpp"
41 #include "Dialogue.hpp"
42 #include "Socket.hpp"
43 #include "Download.hpp"
44
45 #ifdef STDTAGS
46 #undef STDTAGS
47 #endif
48 #define STDTAGS l_shell
49
50 using namespace nepenthes;
51 using namespace std;
52
VFSCommandFTP(VFSNode * parent,VFS * vfs)53 VFSCommandFTP::VFSCommandFTP(VFSNode *parent,VFS *vfs)
54 {
55 m_Name = "ftp.exe";
56 m_ParentNode = parent;
57 m_Type = VFS_EXE;
58 m_VFS = vfs;
59 }
60
~VFSCommandFTP()61 VFSCommandFTP::~VFSCommandFTP()
62 {
63
64 }
65
66
67 /*
68 C:\>ftp -h
69
70 Überträgt Dateien zu und von einem Computer, der den TFTP-Dienst ausführt
71 (auch Daemon genannt).
72
73 FTP kann interaktiv verwendet werden.
74
75 FTP [-v] [-d] [-i] [-n] [-g] [-s:Dateiname] [-a] [-w:Fenstergröße] [-A]
76 [Host]
77
78 -v Unterdrückt das Anzeigen der Rückmeldungen von
79 Remoteservern.
80 -n Unterdrückt das automatische Anmelden nach dem ersten
81 Verbindungsaufbau.
82 -i Deaktiviert die interaktive Eingabe, während mehrere
83 Dateien übertragen werden.
84 -d Aktiviert Debugging.
85 -g Deaktiviert "Globbing" des Dateinamens (siehe auch GLOB-
86 Befehl).
87 -s:Dateiname Gibt eine Textdatei an, die FTP-Befehle enthält. Die
88 Befehle werden nach dem Starten von FTP automatisch
89 ausgeführt.
90 -a Verwendet eine beliebige lokale Schnittstelle, wenn
91 Datenverbindungen gebunden werden.
92 -A Meldet den Benutzer als "Anonymus" an.
93 -w:Puffergröße Überschreibt die Standardgröße des Übertragungspuffers
94 von 4096.
95 Host Gibt den Hostnamen oder die IP-Adresse des Remotehosts
96 an, zu dem eine Verbindung hergestellt wird.
97
98 Hinweis:
99 - Die Befehle "mget" und "mput" akzeptieren y/n/q für yes/no/quit.
100 - Verwenden Sie STRG+C zum Abbrechen von Befehlen.
101 */
102
103
run(vector<string> * paramlist)104 int32_t VFSCommandFTP::run(vector<string> *paramlist)
105 {
106
107 bool direktconnect = true;
108 bool anonymouslogin = false;
109
110 vector <string> slist = *paramlist;
111 vector <string>::iterator it;
112 string host = "nohostyet";
113 string port = "21";
114 string user = "nouseryet";
115 string pass = "nopassyet";
116 string getfile = "nofileyet";
117 string path = "";
118
119 string filename = "";
120 uint8_t downloadflags=0;
121
122
123 for(it=slist.begin();it!=slist.end();it++)
124 {
125 // FTP [-v] [-d] [-i] [-n] [-g] [-s:Dateiname] [-a] [-w:Fenstergr��e] [-A] [Host]
126
127 logDebug("ftp.exe param %s \n",&*it->c_str());
128 if (strncmp(&*it->c_str(),"-v",2) == 0)
129 continue;
130 else
131 if (strncmp(&*it->c_str(),"-d",2) == 0) // debugging
132 continue;
133 else
134 if (strncmp(&*it->c_str(),"-i",2) == 0) // non interactive
135 continue;
136 else
137 if (strncmp(&*it->c_str(),"-n",2) == 0)
138 {
139 direktconnect = false;
140 continue;
141 }
142 else
143 if (strncmp(&*it->c_str(),"-a",2) == 0) // idiotic description i guess binding the port on any interface using active ftp
144 continue;
145 else
146 if (strncmp(&*it->c_str(),"-w:",3) == 0) // window size foobar
147 continue;
148 else
149 if (strncmp(&*it->c_str(),"-s:",3) == 0)
150 {
151 filename = it->substr(3,it->size()-2);
152 }else
153 if (strncmp(&*it->c_str(),"-A",2) == 0) // anonymous login
154 {
155 anonymouslogin = true;
156 user = "anonymous";
157 pass = "guest";
158 }
159 else
160 host = *it;
161 }
162
163 if (filename != "" )
164 {
165 logDebug("Filenameis %s\n",filename.c_str());
166 VFSFile *file = m_VFS->getCurrentDir()->getFile((char *)filename.c_str());
167 if (file == NULL)
168 {
169 logCrit("VFS FTP file %s not found\n",filename.c_str());
170 return 0;
171 }
172 logDebug("file content is is \n%.*s\n",file->getSize(),(char *)file->getData());
173
174 uint32_t i=0;
175 int32_t linestart=0;
176 int32_t linestopp=0;
177 vector <string> ftpcommands;
178 while(i<file->getSize())
179 {
180 if (memcmp(file->getData()+i,"\n",1) == 0)
181 {
182
183 i++;
184 linestopp = i;
185
186 logSpam(" line is '%.*s'\n",linestopp-linestart,file->getData()+linestart);
187 string command( file->getData()+linestart,linestopp-linestart-1);
188 ftpcommands.push_back(command);
189 linestart = linestopp;
190 }
191 i++;
192 }
193
194
195 vector <string>::iterator jt;
196 vector <string> paramlist;
197
198 ftp_command_state state = NEXT_IS_SOMETHING;
199
200 for ( jt=ftpcommands.begin();jt!=ftpcommands.end();jt++ )
201 {
202 string params(&*jt->c_str());
203 i=0;
204 bool haschar = false;
205 uint32_t wordstart=0;
206 uint32_t wordstopp=0;
207 paramlist.clear();
208 while ( i<=params.size() )
209 {
210 if ( ( ( params[i] == ' ' || params[i] == '\0') && haschar == true) )
211 {
212 wordstopp = i;
213 string word = params.substr(wordstart,wordstopp-wordstart);
214 logDebug("Word is %i %i '%s' \n",wordstart,wordstopp,word.c_str());
215 paramlist.push_back(word);
216 haschar = false;
217 } else
218 if ( isgraph(params[i]) && haschar == false )
219 {
220 haschar = true;
221 wordstart = i;
222 }
223 i++;
224 }
225
226
227
228 switch (state)
229 {
230
231 case NEXT_IS_SOMETHING:
232 if ( strncasecmp((char *)&*jt->c_str(),"open",4) == 0 )
233 {
234 logSpam("open line %s \n",&*jt->c_str());
235 switch(paramlist.size())
236 {
237 case 1:
238 state = NEXT_IS_HOST;
239 break;
240 default:
241 host = paramlist[1];
242 if ( paramlist.size() >=3 )
243 port = paramlist[2];
244 else
245 port = "21";
246
247 if(direktconnect == true && anonymouslogin == false)
248 {
249 state = NEXT_IS_USER;
250 }else
251 {
252 state = NEXT_IS_SOMETHING;
253 }
254
255 break;
256
257 }
258
259 logDebug("ftp://%s:%s\n",host.c_str(),port.c_str());
260 } else
261 if ( strncasecmp((char *)&*jt->c_str(),"user",4) == 0 )
262 {
263 if ( direktconnect == true )
264 {
265 logCrit("VFS FTP State ERROR user\n");
266 } else
267 {
268
269 switch ( paramlist.size() )
270 {
271 case 1:
272 state = NEXT_IS_USER;
273 break;
274
275 case 2:
276 user = paramlist[1];
277 state = NEXT_IS_PASS;
278 break;
279 case 3:
280 user = paramlist[1];
281 pass = paramlist[2];
282 break;
283 }
284 logDebug("ftp://%s:%s@%s:%s\n",user.c_str(),pass.c_str(),host.c_str(),port.c_str());
285 }
286 } else
287 if ( strncasecmp((char *)&*jt->c_str(),"get",3) == 0 )
288 {
289 switch(paramlist.size())
290 {
291 case 1:
292 state = NEXT_IS_FILE;
293 logDebug("get without param, next arg is filename\n");
294 break;
295 default:
296 getfile = paramlist[1];
297 // logDebug("ftp://%s:%s@%s:%s/%s\n",user.c_str(),pass.c_str(),host.c_str(),port.c_str(),getfile.c_str());
298 startDownload(host,port,user,pass,path,getfile,downloadflags);
299 }
300 }else
301 if ( strncasecmp((char *)&*jt->c_str(),"binary",6) == 0 ||
302 strncasecmp((char *)&*jt->c_str(),"bin",3) == 0)
303 {
304 downloadflags |= DF_TYPE_BINARY;
305 }else
306 if ( strncasecmp((char *)&*jt->c_str(),"cd",2) == 0 )
307 {
308 switch ( paramlist.size() )
309 {
310 case 1:
311 state = NEXT_IS_PATH;
312 break;
313
314 case 2:
315 path = paramlist[1];
316 break;
317 }
318
319 }
320
321 break;
322
323
324
325 case NEXT_IS_HOST:
326 switch ( paramlist.size() )
327 {
328
329 case 1:
330 host = paramlist[0];
331 port = "21";
332 break;
333
334 case 2:
335 host = paramlist[0];
336 port = paramlist[1];
337 break;
338 }
339
340 if(direktconnect == true && anonymouslogin == false )
341 {
342 state = NEXT_IS_USER;
343 }else
344 {
345 state = NEXT_IS_SOMETHING;
346 }
347 break;
348
349
350 case NEXT_IS_PORT:
351 break;
352
353 case NEXT_IS_USER:
354 switch ( paramlist.size() )
355 {
356 case 1:
357 user = paramlist[0];
358 state = NEXT_IS_PASS;
359 break;
360
361 default:
362 logCrit("Broken State NEXT_IS_USER\n");
363 state = NEXT_IS_SOMETHING;
364 break;
365 }
366 break;
367
368 case NEXT_IS_PASS:
369 pass = paramlist[0];
370 state = NEXT_IS_SOMETHING;
371 break;
372
373
374 case NEXT_IS_FILE:
375 getfile = paramlist[0];
376 startDownload(host,port,user,pass,path,getfile,downloadflags);
377 state = NEXT_IS_SOMETHING;
378 break;
379
380 case NEXT_IS_PATH:
381 path = paramlist[0];
382 state = NEXT_IS_SOMETHING;
383 break;
384
385 }
386
387 }
388
389 }
390 return 0;
391 }
392
startDownload(string host,string port,string user,string pass,string path,string getfile,uint8_t downloadflags)393 bool VFSCommandFTP::startDownload(string host, string port, string user, string pass, string path, string getfile, uint8_t downloadflags)
394 {
395 logPF();
396 string url;
397 string file;
398
399 if (path == "")
400 {
401 url = "ftp://" + user + ":" + pass + "@" + host+ ":" + port + "/" + getfile;
402 }else
403 {
404 url = "ftp://" + user + ":" + pass + "@" + host+ ":" + port;
405
406 int pathlen = path.size()-1;
407 if (path[0] != '/' )
408 {
409 url += "/" + path;
410 file += "/" + path;
411 }
412 if (path[pathlen] != '/')
413 {
414 url += "/";
415 file += "/";
416 }
417 url += getfile;
418 file += getfile;
419 }
420
421 uint32_t remotehost = 0;
422 uint32_t localhost = 0;
423
424 if (m_VFS->getDialogue()->getSocket() != NULL)
425 {
426 logSpam("VFSCommandFTP Setting Hosts %i %i\n",remotehost,localhost);
427 remotehost = m_VFS->getDialogue()->getSocket()->getRemoteHost();
428 localhost = m_VFS->getDialogue()->getSocket()->getLocalHost();
429 }
430
431 logSpam("VFSCommandFTP LocalHost %s\n",inet_ntoa(*(in_addr *)&localhost));
432 logSpam("VFSCommandFTP RemoteHost %s\n",inet_ntoa(*(in_addr *)&remotehost));
433
434 if (strstr(user.c_str(),"@") == NULL && strstr(pass.c_str(),"@") == NULL)
435 {
436 g_Nepenthes->getDownloadMgr()->downloadUrl( localhost,
437 (char *)url.c_str(),
438 remotehost,
439 (char *)url.c_str(),
440 downloadflags);
441 }else
442 {
443 g_Nepenthes->getDownloadMgr()->downloadUrl( localhost,
444 (char *)"ftp",
445 (char *)user.c_str(),
446 (char *)pass.c_str(),
447 (char *)host.c_str(),
448 (char *)port.c_str(),
449 (char *)file.c_str(),
450 remotehost,
451 downloadflags);
452 }
453 return true;
454 }
455