00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <sys/stat.h>
00013 #include <sys/unistd.h>
00014 #include <OPENR/OSyslog.h>
00015 #include <OPENR/ODebug.h>
00016 #include <OPENR/OCalendarTime.h>
00017 #include <stdlib.h>
00018 #include "FtpDTP.h"
00019 #include <stdio.h>
00020
00021 Port
00022 FtpDTP::SetIP(IPAddress ip)
00023 {
00024 connectIP = ip;
00025 connectPort = FTP_PASV_DATA_PORT + (int)continuation;
00026 passive = true;
00027 Listen();
00028 return connectPort;
00029 }
00030
00031 bool
00032 FtpDTP::SetPort(char* ipport)
00033 {
00034 longword buf;
00035 uint32 ip = 0;
00036 uint16 port = 0;
00037
00038 buf = atoi(ipport);
00039 ip |= (buf << 24);
00040 while (*ipport++ != ',') {
00041 ;
00042 }
00043 buf = atoi(ipport);
00044 ip |= (buf << 16);
00045 while (*ipport++ != ',') {
00046 ;
00047 }
00048 buf = atoi(ipport);
00049 ip |= (buf << 8);
00050 while (*ipport++ != ',') {
00051 ;
00052 }
00053 buf = atoi(ipport);
00054 ip |= buf;
00055 while (*ipport++ != ',') {
00056 ;
00057 }
00058
00059 buf = atoi(ipport);
00060 port |= (buf << 8);
00061 while (*ipport++ != ',') {
00062 ;
00063 }
00064 buf = atoi(ipport);
00065 port |= buf;
00066
00067 OSYSDEBUG(("FtpDTP::Port():Set IP:%x Port:%d\n", ip, port));
00068 connectIP = (IPAddress)ip;
00069 connectPort = (Port)port;
00070 passive = false;
00071 return true;
00072 }
00073
00074 bool
00075 FtpDTP::Store(char* filename)
00076 {
00077 char file[MAX_STRING_LENGTH * 2];
00078 method = FTP_METHOD_STOR;
00079
00080 if (filename[0] == '/') {
00081 sprintf(file, "%s", filename);
00082 } else {
00083 sprintf(file, "%s%s", ftpDir, filename);
00084 }
00085
00086 DirNorm(file);
00087
00088 if (!strncmp(file, ftpHome, strlen(ftpHome))) {
00089 if((fp = fopen(file, "wb")) == NULL) {
00090 OSYSLOG1((osyslogERROR, "Ftpd::File Open Failed %s.", file));
00091 return false;
00092 }
00093 } else {
00094 return false;
00095 }
00096
00097 strncpy(ftpFile, filename, MAX_STRING_LENGTH);
00098
00099 if (passive) {
00100 if (connection.state == CONNECTION_CONNECTED) {
00101 connection.recvSize = 0;
00102 Receive();
00103 }
00104 } else {
00105 Connect();
00106 }
00107 return true;
00108 }
00109
00110 bool
00111 FtpDTP::Retrieve(char* filename)
00112 {
00113 char file[MAX_STRING_LENGTH * 2];
00114 method = FTP_METHOD_RETR;
00115
00116 if (filename[0] == '/') {
00117 sprintf(file, "%s", filename);
00118 } else {
00119 sprintf(file, "%s%s", ftpDir, filename);
00120 }
00121
00122 DirNorm(file);
00123
00124 if (!strncmp(file, ftpHome, strlen(ftpHome))) {
00125 if((fp = fopen(file, "rb")) == NULL) {
00126 OSYSLOG1((osyslogERROR, "FtpDTP::File Open Failed %s.", file));
00127 return false;
00128 }
00129 } else {
00130 return false;
00131 }
00132
00133 strncpy(ftpFile, filename, MAX_STRING_LENGTH);
00134
00135 if (passive) {
00136 if (connection.state == CONNECTION_CONNECTED) {
00137 RetrieveSend();
00138 }
00139 } else {
00140 Connect();
00141 }
00142 return true;
00143 }
00144
00145 bool
00146 FtpDTP::RetrieveSend()
00147 {
00148 if (dataType == FTP_DATA_A) {
00149 connection.recvSize
00150 = fread(connection.recvData, 1, FTP_BUFFER_SIZE / 2, fp);
00151 if (FTP_BUFFER_SIZE / 2 > connection.recvSize) {
00152 byte *cur_r = connection.recvData;
00153 byte *cur_s = connection.sendData;
00154 connection.sendSize = connection.recvSize;
00155 for (int i = 0; i < connection.recvSize; i++, cur_r++) {
00156 if (*cur_r == LF) {
00157 if ((cur_r != connection.recvData)
00158 && (*(cur_r - 1) != CR)) {
00159 *cur_s++ = CR;
00160 connection.sendSize++;
00161 }
00162 *cur_s++ = *cur_r;
00163 } else {
00164 *cur_s++ = *cur_r;
00165 }
00166 }
00167 fclose(fp);
00168 method = FTP_METHOD_NOOP;
00169 Send();
00170 } else {
00171 byte *cur_r = connection.recvData;
00172 byte *cur_s = connection.sendData;
00173 connection.sendSize = connection.recvSize;
00174 for (int i = 0; i < connection.recvSize; i++, cur_r++) {
00175 if (*cur_r == LF) {
00176 if ((cur_r != connection.recvData)
00177 && (*(cur_r - 1) != CR)) {
00178 *cur_s++ = CR;
00179 connection.sendSize++;
00180 }
00181 *cur_s++ = *cur_r;
00182 } else {
00183 *cur_s++ = *cur_r;
00184 }
00185 }
00186 Send();
00187 }
00188 } else {
00189 connection.sendSize
00190 = fread(connection.sendData, 1, FTP_BUFFER_SIZE, fp);
00191 if (FTP_BUFFER_SIZE > connection.sendSize) {
00192 fclose(fp);
00193 method = FTP_METHOD_NOOP;
00194 Send();
00195 } else {
00196 Send();
00197 }
00198 }
00199 return true;
00200 }
00201
00202 bool
00203 FtpDTP::RenameFrom(char *file)
00204 {
00205 char tmp[MAX_STRING_LENGTH * 2];
00206
00207 if (file[0] == '/') {
00208 sprintf(tmp, "%s", file);
00209 } else {
00210 sprintf(tmp, "%s%s", ftpDir, file);
00211 }
00212
00213 DirNorm(tmp);
00214
00215 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00216 FILE *fp = fopen(tmp, "r");
00217 if (fp != NULL) {
00218 strncpy(ftpFile, tmp, MAX_STRING_LENGTH);
00219 fclose(fp);
00220 return true;
00221 }
00222 }
00223
00224 return false;
00225 }
00226
00227 bool
00228 FtpDTP::RenameTo(char *file)
00229 {
00230 char tmp[MAX_STRING_LENGTH * 2];
00231
00232 if (file[0] == '/') {
00233 sprintf(tmp, "%s", file);
00234 } else {
00235 sprintf(tmp, "%s%s", ftpDir, file);
00236 }
00237
00238 DirNorm(tmp);
00239
00240 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00241 int ret = rename(ftpFile, tmp);
00242 if (ret == 0) {
00243 strcpy(ftpFile, "");
00244 return true;
00245 }
00246 }
00247
00248 strcpy(ftpFile, "");
00249 return false;
00250 }
00251
00252 bool
00253 FtpDTP::List(char* dir)
00254 {
00255 char tmp[MAX_STRING_LENGTH * 2];
00256 total = true;
00257
00258 if ((dir[0] != '\0') && (dir[0] == '/')) {
00259 sprintf(tmp, "%s/", dir);
00260 listLong = false;
00261 } else if ((dir[0] != '\0') && (dir[0] == '-')) {
00262 sprintf(tmp, "%s", ftpDir);
00263 listLong = true;
00264 } else {
00265 sprintf(tmp, "%s%s", ftpDir, dir);
00266 listLong = false;
00267 }
00268
00269 listLong = true;
00270
00271 DirNorm(tmp);
00272
00273 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00274 if (dirp = opendir(tmp)) {
00275 method = FTP_METHOD_LIST;
00276 strcpy(ftpFile, tmp);
00277 if (passive) {
00278 if (connection.state == CONNECTION_CONNECTED) {
00279 if (!ListSend()) {
00280 Close();
00281 }
00282 }
00283 } else {
00284 Connect();
00285 }
00286 return true;
00287 }
00288 }
00289 return false;
00290 }
00291
00292 bool
00293 FtpDTP::ListSend()
00294 {
00295 dirent *entry;
00296 char tmp[MAX_STRING_LENGTH];
00297
00298 if (total) {
00299 sprintf((char *)connection.sendData,
00300 "total %d\r\n", 0);
00301 connection.sendSize = strlen((char *)connection.sendData);
00302 Send();
00303 total = false;
00304 return true;
00305 }
00306
00307 entry = readdir(dirp);
00308 if (entry) {
00309 struct stat statbuf;
00310 sprintf(tmp, "%s/%s", ftpFile, entry->d_name);
00311 DirNorm(tmp);
00312
00313 int ret = stat(tmp, &statbuf);
00314 if (listLong) {
00315 sprintf((char *)connection.sendData,
00316 "%c%c%c%c%c%c%c%c%c%c %x %s %s %-d %s %d %d %s\r\n",
00317 (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'd' : '-',
00318 (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
00319 (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
00320 (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
00321 (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
00322 (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
00323 (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
00324 (statbuf.st_mode & S_IRUSR) ? 'r' : '-',
00325 (statbuf.st_mode & S_IWUSR) ? 'w' : '-',
00326 (statbuf.st_mode & S_IFMT) == S_IFDIR ? 'x' : '-',
00327 0,
00328 "AIBO",
00329 "AIBO",
00330 statbuf.st_size,
00331 "May",
00332 11,
00333 1999,
00334 entry->d_name
00335 );
00336 } else {
00337 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
00338 sprintf((char *)connection.sendData,
00339 "%s/\r\n",
00340 entry->d_name);
00341 } else {
00342 sprintf((char *)connection.sendData,
00343 "%s\r\n",
00344 entry->d_name);
00345 }
00346 }
00347 connection.sendSize = strlen((char *)connection.sendData);
00348 Send();
00349 } else {
00350 method = FTP_METHOD_NOOP;
00351 closedir(dirp);
00352 return false;
00353 }
00354
00355 return true;
00356 }
00357
00358 bool
00359 FtpDTP::ChangeDir(char* dir)
00360 {
00361 char tmp[MAX_STRING_LENGTH * 2];
00362
00363 if (dir[0] == '/') {
00364 sprintf(tmp, "%s/", dir);
00365 } else {
00366 sprintf(tmp, "%s%s/", ftpDir, dir);
00367 }
00368
00369 DirNorm(tmp);
00370
00371 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00372 DIR* tmpdirp;
00373 if (tmpdirp = opendir(tmp)) {
00374 closedir(tmpdirp);
00375 strcpy(ftpDir, tmp);
00376 return true;
00377 }
00378 }
00379
00380 return false;
00381 }
00382
00383 bool
00384 FtpDTP::MakeDir(char* dir)
00385 {
00386 char tmp[MAX_STRING_LENGTH * 2];
00387
00388 if (dir[0] == '/') {
00389 sprintf(tmp, "%s", dir);
00390 } else {
00391 sprintf(tmp, "%s%s", ftpDir, dir);
00392 }
00393
00394 DirNorm(tmp);
00395
00396 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00397 if (!mkdir(tmp, 0777)) {
00398 return true;
00399 }
00400 }
00401
00402 return false;
00403 }
00404
00405 bool
00406 FtpDTP::RemoveDir(char* dir)
00407 {
00408 char tmp[MAX_STRING_LENGTH * 2];
00409
00410 if (dir[0] == '/') {
00411 sprintf(tmp, "%s", dir);
00412 } else {
00413 sprintf(tmp, "%s%s", ftpDir, dir);
00414 }
00415
00416 DirNorm(tmp);
00417
00418 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00419 if (!rmdir(tmp)) {
00420 return true;
00421 }
00422 }
00423
00424 return false;
00425 }
00426
00427 bool
00428 FtpDTP::Delete(char* filename)
00429 {
00430 char tmp[MAX_STRING_LENGTH * 2];
00431
00432 if (filename[0] == '/') {
00433 sprintf(tmp, "%s", filename);
00434 } else {
00435 sprintf(tmp, "%s%s", ftpDir, filename);
00436 }
00437
00438 DirNorm(tmp);
00439
00440 if (!strncmp(tmp, ftpHome, strlen(ftpHome))) {
00441 if (!remove(tmp)) {
00442 return true;
00443 }
00444 }
00445
00446 return false;
00447 }
00448
00449 void
00450 FtpDTP::Save(byte *data, int length, bool end)
00451 {
00452 OSYSDEBUG(("FtpDTP::Save %d %d\n", length, end));
00453 if (length) fwrite(data, length, 1, fp);
00454 if (end) {
00455 fclose(fp);
00456 strcpy(ftpFile, "");
00457 }
00458 }
00459
00460 size_t
00461 FtpDTP::GetFileSize(char *name)
00462 {
00463 struct stat statbuf;
00464 int ret = stat(name, &statbuf);
00465 if (ret == 0) {
00466 return statbuf.st_size;
00467 } else {
00468 return 0;
00469 }
00470 }
00471
00472 void
00473 FtpDTP::ResetFilename()
00474 {
00475 strcpy(ftpFile, "");
00476 }
00477
00478 void
00479 FtpDTP::SetUser(char *user)
00480 {
00481 strncpy(ftpUser, user, MAX_STRING_LENGTH);
00482 }
00483
00484 void
00485 FtpDTP::SetHome(char *home)
00486 {
00487 sprintf(ftpHome, "%s/", home);
00488
00489 DirNorm(ftpHome);
00490 strcpy(ftpDir, ftpHome);
00491 }
00492
00493 void
00494 FtpDTP::DirNorm(char *dir)
00495 {
00496 char tmp[MAX_STRING_LENGTH * 2];
00497 int length = strlen(dir);
00498 int cur = 0;
00499
00500 for (int i = 0; i < length + 1; i++) {
00501 OSYSDEBUG(("DirNorm %c\n", dir[i]));
00502 if (dir[i] == '.') {
00503 if ((dir[i + 1] == '.') && (dir[i + 2] == '/')) {
00504 cur -= 2;
00505 while(tmp[cur] != '/') {
00506 cur--;
00507 }
00508 cur++;
00509 } else if (dir[i + 1] == '/') {
00510 i++;
00511 } else {
00512 tmp[cur++] = toupper(dir[i]);
00513 }
00514 } else if (dir[i] == '/') {
00515 if ((cur == 0) || ((cur != 0) && (tmp[cur - 1] != '/'))) {
00516 tmp[cur++] = toupper(dir[i]);
00517 }
00518 } else {
00519 tmp[cur++] = toupper(dir[i]);
00520 }
00521 }
00522
00523 strncpy(dir, tmp, MAX_STRING_LENGTH);
00524 dir[MAX_STRING_LENGTH] = '0';
00525 }