// // PLP - An implementation of the PSION link protocol // // Copyright (C) 1999 Philip Proudman // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // e-mail philip.proudman@btinternet.com #include #include #include #include #include #include #include #include "../defaults.h" #include "ftp.h" #include "rfsv.h" #include "bufferarray.h" #include "bufferstore.h" void ftp::resetUnixPwd() { getcwd(localDir, 500); strcat(localDir, "/"); } ftp::ftp() { resetUnixPwd(); strcpy(psionDir, DEFAULT_DRIVE); strcat(psionDir, DEFAULT_BASE_DIRECTORY); } ftp::~ftp() { } int ftp::session(rfsv &a) { char command[300]; while (getCommand(command, 300)) { if (!strcmp(command, "pwd")) { cout << "Local dir: \"" << localDir << "\"" << endl; cout << "Psion dir: \"" << psionDir << "\"" << endl; } else if (!strcmp(command, "dir")) { if (a.dir(psionDir, NULL) != 0) cerr << "Command failed\n"; } else if (!strncmp(command, "lcd", 3) && strlen(command) > 3) { if (command+3 == 0) { resetUnixPwd(); } else { char temp[500]; cd(localDir, command+4, temp); DIR* d = opendir(temp); if (d) { strcpy(localDir, temp); closedir(d); } else cerr << "No such directory" << endl << "Keeping original directory \"" << localDir << "\"" << endl; } } else if (!strncmp(command, "cd", 2) && strlen(command) > 2) { if (command[2] == 0) { strcpy(psionDir, DEFAULT_DRIVE); strcat(psionDir, DEFAULT_BASE_DIRECTORY); } else { char temp[500]; cd(psionDir, command+3, temp); bufferArray files; if (a.dir(temp, &files) == 0) { strcpy(psionDir, temp); } else cerr << "Keeping original directory \"" << psionDir << "\"" << endl; } } else if (!strncmp(command, "get", 3) && strlen(command) > 3) { char f1[300]; char f2[300]; strcpy(f1, psionDir); strcat(f1, command+4); strcpy(f2, localDir); strcat(f2, command+4); if (a.read(f1, f2) != 0) cerr << "Command failed\n"; else cout << "Transfer complete\n"; } else if (!strncmp(command, "mget", 4) && strlen(command) > 4) { char f1[300]; char f2[300]; bufferArray files; a.dir(psionDir, &files); bool doAll = false; while (!files.empty()) { bufferStore s; s = files.popBuffer(); if (wildcardMatch(command+5, s.getString())) { char temp[100]; if (!doAll) { do { cout << "Get \"" << s.getString() << "\" y,n,Y (yes to all) or l (lowercase filename): "; cout.flush(); cin.getline(temp, 100); } while (temp[1] != 0 || (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != 'n' && temp[0] != 'l')); if (temp[0] == 'Y') doAll = true; } if (doAll) temp[0] = 'y'; if (temp[0] != 'n') { strcpy(f1, psionDir); strcat(f1, s.getString()); strcpy(f2, localDir); strcat(f2, s.getString()); if (temp[0] == 'l') { for (char*p = f2; *p; p++) *p = tolower(*p); } if (a.read(f1, f2) != 0) { cerr << "Command failed - terminating mget\n"; break; } else cout << "Transfer complete\n"; } } } } else if (!strncmp(command, "put", 3) && strlen(command) > 3) { char f1[300]; char f2[300]; strcpy(f1, psionDir); strcat(f1, command+4); strcpy(f2, localDir); strcat(f2, command+4); if (a.write(f2, f1) != 0) cerr << "Command failed\n"; else cout << "Transfer complete\n"; } else if (!strncmp(command, "mput", 4) && strlen(command) > 4) { DIR* d = opendir(localDir); if (d) { struct dirent *de; bool doAll = false; do { de = readdir(d); if (de) { bool isSubDir = false; { // Quick & nasty check to see if this is a sub-directory char temp[500]; cd(localDir, de->d_name, temp); DIR* d2 = opendir(temp); if (d2) { isSubDir = true; closedir(d2); } } if (!isSubDir && wildcardMatch(command+5, de->d_name)) { char temp[100]; if (!doAll) { do { cout << "Put \"" << de->d_name << "\" y,n,Y (yes to all): "; cout.flush(); cin.getline(temp, 100); } while (temp[1] != 0 || (temp[0] != 'y' && temp[0] != 'n' && temp[0] != 'Y')); if (temp[0] == 'Y') doAll = true; } if (doAll) temp[0] = 'y'; if (temp[0] == 'y') { char f1[300]; char f2[300]; strcpy(f1, psionDir); strcat(f1, de->d_name); strcpy(f2, localDir); strcat(f2, de->d_name); if (a.write(f2, f1) != 0) { cerr << "Command failed - terminating mput\n"; break; } else cout << "Transfer complete\n"; } } } } while (de); closedir(d); } else { cerr << "Error in directory name \"" << localDir << "\"\n"; } } else if (!strncmp(command, "del", 3) && strlen(command) > 3) { char f1[300]; strcpy(f1, psionDir); strcat(f1, command+4); if (a.del(f1) != 0) cerr << "No such file\n"; else cout << "Ok\n"; } else if (!strncmp(command, "mkdir", 5) && strlen(command) > 5) { char f1[300]; strcpy(f1, psionDir); strcat(f1, command+6); if (a.mkdir(f1) != 0) cerr << "Command failed\n"; else cout << "Ok\n"; } else if (command[0] == '!') { char com[1024]; strcpy(com, "cd "); strcat(com, localDir); strcat(com, "; "); strcat(com, command+1); system(com); } else if (!strcmp(command, "??")) { cout << "w = writeable" << endl; cout << "h = hidden" << endl; cout << "s = system" << endl; cout << "d = directory" << endl; cout << "a = archive" << endl; cout << "m = modified" << endl; cout << "v = volume" << endl; cout << "n = normal" << endl; cout << "t = temporary" << endl; cout << "c = compressed" << endl << endl; cout << "r = readable" << endl; cout << "e = executable" << endl; cout << "S = stream" << endl; cout << "T = text" << endl << endl; } else if (strcmp(command, "bye")) { if (strcmp(command, "?")) cerr << "Unknown command" << endl; cerr << " pwd" << endl; cerr << " dir" << endl; cerr << " cd " << endl; cerr << " lcd " << endl; cerr << " !" << endl; cerr << " get " << endl; cerr << " put " << endl; cerr << " mget (works on whole directort, interactively)" << endl; cerr << " mput (works on whole directory, interactively)" << endl; cerr << " del " << endl; cerr << " mkdir " << endl; cerr << " ?? (show description of file properties)"; cerr << " bye" << endl; } else break; } return 0; } bool ftp::getCommand(char* buf, int bufLen) const { cout << "> "; cout.flush(); cin.getline(buf, bufLen); return !cin.eof(); } // Unix utilities bool ftp::unixDirExists(const char* dir) { return false; } void ftp::getUnixDir(bufferArray &files) { } void ftp::cd(const char *source, const char* cdto, char *dest) { if (cdto[0] == '/' || cdto[0] == '\\' || cdto[1] == ':') { strcpy(dest, cdto); char cc = dest[strlen(dest)-1]; if (cc != '/' && cc != '\\') strcat(dest, "/"); } else { char start[200]; strcpy(start, source); while (*cdto) { char bit[200]; int j; for (j=0; cdto[j] && cdto[j] != '/' && cdto[j] != '\\'; j++) bit[j] = cdto[j]; bit[j] = 0; cdto += j; if (*cdto) cdto++; if (!strcmp(bit, "..")) { strcpy(dest, start); int i; for (i=strlen(dest)-2; i>=0; i--) { if (dest[i] == '/' || dest[i] == '\\') { dest[i+1] = 0; break; } } } else { strcpy(dest, start); strcat(dest, bit); strcat(dest, "/"); } strcpy(start, dest); } } } bool ftp::wildcardMatch(const char* wild, const char* file) const { // Good luck if you're reading this :-) for (; *file && *wild; ++file, ++wild) { if (*file != *wild) { if (*wild != '?') { if (*wild == '*') { ++wild; if (*wild) { for (;*file; ++file) { if (wildcardMatch(wild, file)) return true; } return false; } else return true; } else return false; } } } return (!(*file) && !(*wild)); }