00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00094 
00095 
00096 #include <sys/version.h>
00097 
00098 #include <sys/socket.h>
00099 #include <netinet/tcp.h>
00100 #include <sys/timer.h>
00101 
00102 #include <string.h>
00103 #include <stdio.h>
00104 #include <stdlib.h>
00105 #include <io.h>
00106 #include <fcntl.h>
00107 #include <sys/stat.h>
00108 #include <dirent.h>
00109 #include <unistd.h>
00110 #include <memdebug.h>
00111 
00112 #include <pro/ftpd.h>
00113 
00114 #ifdef FTPD_DEBUG
00115 #include <sys/heap.h>
00116 #endif
00117 
00124 
00131 
00137 #ifndef FTP_ROOTPATH
00138 #define FTP_ROOTPATH "PNUT:"
00139 #endif
00140 
00146 #ifndef FTP_DATA_PORT
00147 #define FTP_DATA_PORT   20
00148 #endif
00149 
00152 static char *ftp_root;
00153 static char *ftp_user;
00154 static char *ftp_pass;
00155 
00156 
00157 
00158 
00159 
00160 static prog_char cmd_cwd_P[] = "CWD";
00161 static prog_char cmd_dele_P[] = "DELE";
00162 static prog_char cmd_list_P[] = "LIST";
00163 static prog_char cmd_mkd_P[] = "MKD";
00164 static prog_char cmd_xmkd_P[] = "XMKD";
00165 static prog_char cmd_nlst_P[] = "NLST";
00166 static prog_char cmd_noop_P[] = "NOOP";
00167 static prog_char cmd_pass_P[] = "PASS";
00168 static prog_char cmd_pasv_P[] = "PASV";
00169 static prog_char cmd_port_P[] = "PORT";
00170 static prog_char cmd_pwd_P[] = "PWD";
00171 static prog_char cmd_xpwd_P[] = "XPWD";
00172 static prog_char cmd_quit_P[] = "QUIT";
00173 static prog_char cmd_retr_P[] = "RETR";
00174 static prog_char cmd_rmd_P[] = "RMD";
00175 static prog_char cmd_xrmd_P[] = "XRMD";
00176 static prog_char cmd_stor_P[] = "STOR";
00177 static prog_char cmd_syst_P[] = "SYST";
00178 static prog_char cmd_type_P[] = "TYPE";
00179 static prog_char cmd_user_P[] = "USER";
00180 static prog_char cmd_rename1_P[] = "RNFR";
00181 static prog_char cmd_rename2_P[] = "RNTO";
00182 
00183 
00184 static char *mon_name = "JanFebMarAprMayJunJulAugSepOctNovDec";
00185 
00186 static prog_char rep_banner[] = "220 Nut/OS FTP %s ready at %.3s%3d %02d:%02d:%02d\r\n";
00187 
00200 static void SplitCmdArg(char * line, char ** cmd, char ** args)
00201 {
00202     
00203     while (*line && *line <= ' ') {
00204         line++;
00205     }
00206 
00207     
00208     *cmd = line;
00209     while (*line > ' ') {
00210         if (*line >= (uint8_t) 'a' && *line <= (uint8_t) 'z') {
00211             *line -= (uint8_t) 'a' - 'A';
00212         }
00213         line++;
00214     }
00215 
00216     
00217     if (*line) {
00218         *line++ = '\0';
00219     }
00220 
00221     
00222     while (*line && *line <= ' ') {
00223         ++line;
00224     }
00225 
00226     
00227     *args = line;
00228     while (*line && *line != '\r' && *line != '\n') {
00229         line++;
00230     }
00231 
00232     
00233     *line = 0;
00234 }
00235 
00251 static int ParseIpPort(CONST char * arg, uint32_t * ip, uint16_t * port)
00252 {
00253     int rc;
00254 
00255     *ip = 0;
00256     *port = 0;
00257     for (rc = 0; rc < 6; rc++) {
00258         if (*arg < '0' || *arg > '9') {
00259             break;
00260         }
00261         if (rc < 4) {
00262             *ip >>= 8;
00263             *ip += atol(arg) << 24;
00264         } else {
00265             *port <<= 8;
00266             *port += atoi(arg);
00267         }
00268         while (*arg && *arg != ',') {
00269             arg++;
00270         }
00271         if (*arg == ',') {
00272             arg++;
00273         }
00274     }
00275     return rc;
00276 }
00277 
00287 int NutFtpRespondOk(FTPSESSION * session, int code)
00288 {
00289     static prog_char fmt_P[] = "%d OK\r\n";
00290 
00291 #ifdef FTPD_DEBUG
00292     printf("\n<'%d OK' ", code);
00293 #endif
00294     fprintf_P(session->ftp_stream, fmt_P, code);
00295     fflush(session->ftp_stream);
00296 
00297     return 0;
00298 }
00299 
00309 int NutFtpRespondBad(FTPSESSION * session, int code)
00310 {
00311     static prog_char fmt_P[] = "%d Failed\r\n";
00312 
00313 #ifdef FTPD_DEBUG
00314     printf("\n<'%d Failed' ", code);
00315 #endif
00316     fprintf_P(session->ftp_stream, fmt_P, code);
00317     fflush(session->ftp_stream);
00318 
00319     return 0;
00320 }
00321 
00331 int NutFtpSendMode(FTPSESSION * session, int binary)
00332 {
00333     static prog_char intro_P[] = "150 Opening ";
00334     static prog_char amode_P[] = "ASCII.\r\n";
00335     static prog_char bmode_P[] = "BINARY.\r\n";
00336 
00337 #ifdef FTPD_DEBUG
00338     printf("\n<'150 Opening %s' ", binary ? "BINARY" : "ASCII");
00339 #endif
00340     fputs_P(intro_P, session->ftp_stream);
00341     fputs_P(binary ? bmode_P : amode_P, session->ftp_stream);
00342     fflush(session->ftp_stream);
00343 
00344     return 0;
00345 }
00346 
00367 char *CreateFullPathName(char *root, char *work, char *path)
00368 {
00369     char *full;
00370     char *cp;
00371     size_t rl = root ? strlen(root) : 0;
00372     size_t wl = work ? strlen(work) : 0;
00373     size_t pl = path ? strlen(path) : 0;
00374 
00375     
00376     if (rl && *(root + rl - 1) == '/') {
00377         rl--;
00378     }
00379     if (wl && *(work + wl - 1) == '/') {
00380         wl--;
00381     }
00382 
00383     if ((full = malloc(rl + wl + pl + 3)) != NULL) {
00384         
00385         cp = full;
00386         if (rl) {
00387             cp = strcpy(full, root) + rl;
00388         }
00389 
00390         
00391         if(pl == 0 || *path != '/') {
00392             if (wl) {
00393                 if (*work != '/') {
00394                     *cp++ = '/';
00395                 }
00396                 cp = strcpy(cp, work) + wl;
00397             }
00398             *cp++ = '/';
00399             rl++;
00400         }
00401 
00402         if (pl) {
00403             *cp = 0;
00404             work = full + rl;
00405 
00406             while (*path) {
00407                 
00408                 if (*path == '/') {
00409                     
00410                     if ((cp == full) || (*(cp-1) != '/')) {
00411                         *cp++ = *path++;
00412                     }
00413                     while (*path == '/') {
00414                         path++;
00415                     }
00416                 }
00417                 
00418                 if (*path == '.') {
00419                     path++;
00420                     if (*path == '/') {
00421                         path++;
00422                         continue;
00423                     }
00424                     if (*path == 0) {
00425                         break;
00426                     }
00427                     if (*path == '.') {
00428                         path++;
00429                         if (*path == '/' || *path == 0) {
00430                             if (cp != work) {
00431                                 cp--;
00432                                 while (cp != work) {
00433                                     cp--;
00434                                     if (*cp == '/') {
00435                                         break;
00436                                     }
00437                                 }
00438                             }
00439                             continue;
00440                         }
00441                         path--;
00442                     }
00443                     path--;
00444                 }
00445                 
00446                 while (*path && *path != '/') {
00447                     *cp++ = *path++;
00448                 }
00449             }
00450         }
00451         *cp = 0;
00452     }
00453     return full;
00454 }
00455 
00465 TCPSOCKET *NutFtpDataConnect(FTPSESSION * session)
00466 {
00467 #ifdef FTPD_DEBUG
00468     static prog_char errorcode_P[] = "errorcode of active socket: %i\n";
00469     static prog_char socfailed_P[] = "Create socket failed";
00470 #endif
00471     TCPSOCKET *sock;
00472     int rc;
00473 
00474     if ((sock = NutTcpCreateSocket()) != 0) {
00475 
00476         if (session->ftp_maxseg) {
00477             NutTcpSetSockOpt(sock, TCP_MAXSEG, &session->ftp_maxseg, sizeof(session->ftp_maxseg));
00478         }
00479         if (session->ftp_passive) {
00480             rc = NutTcpAccept(sock, session->ftp_data_port);
00481         } else {
00482             rc = NutTcpConnect(sock, session->ftp_data_ip, session->ftp_data_port);
00483 #ifdef FTPD_DEBUG
00484             if (rc) {
00485               int errorcode = NutTcpError(sock);
00486               printf_P(errorcode_P, errorcode);
00487             }
00488 #endif
00489         }
00490         if (rc) {
00491             NutTcpCloseSocket(sock);
00492             sock = 0;
00493         }
00494     }
00495 #ifdef FTPD_DEBUG
00496     else {
00497         puts_P(socfailed_P);
00498     }
00499 #endif
00500     return sock;
00501 }
00502 
00516 int NutRegisterFtpRoot(CONST char *path)
00517 {
00518     
00519     if (path == NULL || *path == 0) {
00520         
00521         if (ftp_root) {
00522             free(ftp_root);
00523         }
00524         if ((ftp_root = malloc(sizeof(FTP_ROOTPATH))) == 0) {
00525             return -1;
00526         }
00527         strcpy(ftp_root, FTP_ROOTPATH);
00528     }
00529 
00530     
00531     else {
00532         char *cp = strchr(path, ':');
00533         int len = strlen(path);
00534 
00535         
00536         if (len < 2 || cp == 0 || (*++cp && *cp != '/')) {
00537             return -1;
00538         }
00539 
00540         
00541         if ((cp = malloc(len + 1)) == 0) {
00542             return -1;
00543         }
00544 
00545         
00546         strcpy(cp, path);
00547         if (ftp_root) {
00548             free(ftp_root);
00549         }
00550         ftp_root = cp;
00551 
00552         
00553         cp = cp + strlen(cp) - 1;
00554         if (*cp == '/') {
00555             *cp = 0;
00556         }
00557     }
00558     return 0;
00559 }
00560 
00576 int NutRegisterFtpUser(CONST char *user, CONST char *pass)
00577 {
00578     if (ftp_user) {
00579         free(ftp_user);
00580         ftp_user = NULL;
00581     }
00582     if (user && *user) {
00583         if ((ftp_user = strdup(user)) == NULL) {
00584             return -1;
00585         }
00586     }
00587     if (ftp_pass) {
00588         free(ftp_pass);
00589         ftp_pass = NULL;
00590     }
00591     if (pass && *pass) {
00592         if ((ftp_pass = strdup(pass)) == NULL) {
00593             return -1;
00594         }
00595     }
00596     return 0;
00597 }
00598 
00599 
00609 FTPSESSION *NutFtpOpenSession(TCPSOCKET * sock)
00610 {
00611     FTPSESSION *session;
00612 
00613     session = malloc(sizeof(FTPSESSION));
00614 
00615     if (session) {
00616         memset(session, 0, sizeof(FTPSESSION));
00617         session->ftp_data_port = FTP_DATA_PORT;
00618         session->ftp_maxseg = sock->so_mss;
00619         session->ftp_sock = sock;
00620 
00621         
00622         if ((session->ftp_cwd = malloc(2)) == 0) {
00623             free(session);
00624             session = 0;
00625         } else {
00626             session->ftp_cwd[0] = '/';
00627             session->ftp_cwd[1] = 0;
00628 
00629             
00630 
00631 
00632 
00633 
00634             if ((session->ftp_stream = _fdopen((int) sock, "r+b")) == 0) {
00635                 free(session->ftp_cwd);
00636                 free(session);
00637                 session = 0;
00638             }
00639         }
00640     }
00641     return session;
00642 }
00643 
00650 void NutFtpCloseSession(FTPSESSION * session)
00651 {
00652     if (session) {
00653         
00654         fclose(session->ftp_stream);
00655         if (session->ftp_cwd) {
00656             free(session->ftp_cwd);
00657         }
00658         if (session->ftp_renamesource) {
00659             free(session->ftp_renamesource);
00660         }
00661         free(session);
00662     }
00663 }
00664 
00675 int NutFtpProcessCwd(FTPSESSION * session, char *path)
00676 {
00677     struct stat st;
00678     char *cp = path + strlen(ftp_root);
00679 
00680     if (*cp && strcmp(cp, "/")) {
00681         
00682 
00683 
00684         if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
00685             return NutFtpRespondBad(session, 550);
00686         }
00687     }
00688 
00689     
00690 
00691 
00692     if (*cp == 0) {
00693         cp = "/";
00694     }
00695     if (session->ftp_cwd) {
00696         free(session->ftp_cwd);
00697     }
00698     if ((session->ftp_cwd = strdup(cp)) == NULL) {
00699         return NutFtpRespondBad(session, 550);
00700     }
00701     return NutFtpRespondOk(session, 250);
00702 }
00703 
00716 int NutFtpProcessDelete(FTPSESSION * session, char *path)
00717 {
00718     if (unlink(path)) {
00719         return NutFtpRespondBad(session, 550);
00720     }
00721     return NutFtpRespondOk(session, 250);
00722 }
00723 
00741 int NutFtpTransferFile(FTPSESSION * session, char *path, int mode)
00742 {
00743 #ifdef FTPD_DEBUG
00744     static prog_char dataconnectfailed_P[] = "NutFtpDataConnect failed";
00745 #endif
00746     TCPSOCKET *sock;
00747     int ec = 550;
00748     int fh = -1;
00749     
00750     if (mode) {
00751         
00752         struct stat st;
00753         if (stat(path, &st) == 0) {
00754             if (S_ISREG(st.st_mode)) {
00755                 fh = _open(path, _O_BINARY | _O_RDONLY);
00756             } else {
00757 #ifdef FTPD_DEBUG
00758                printf("Not a regular file\n");
00759 #endif
00760             }
00761         } else {
00762 #ifdef FTPD_DEBUG
00763             printf("'%s' stat() failed\n", path);
00764 #endif
00765         }
00766     }
00767     
00768     else {
00769         fh = _open(path, _O_CREAT | _O_TRUNC);
00770     }
00771     if (fh != -1) {
00772         
00773         NutFtpSendMode(session, session->ftp_tran_mode);
00774         if ((sock = NutFtpDataConnect(session)) != 0) {
00775             uint16_t mss = sock->so_mss;
00776             uint8_t *buf;
00777 
00778             if (mss < 256) {
00779                 mss = 256;
00780             }
00781             if ((buf = malloc(mss)) != 0) {
00782                 int got;
00783 
00784                 ec = 0;
00785 
00786                 
00787                 if (mode) {
00788                     while ((got = _read(fh, buf, mss)) > 0) {
00789                         int send = 0;
00790                         int retcode;
00791                         uint8_t timeout = 0;
00792                         
00793 
00794 
00795                         do {
00796                             retcode = NutTcpSend(sock, buf+send, got-send);
00797                             send += retcode; 
00798                             if (send == 0) {
00799                                 timeout++;
00800                                 NutSleep(10);
00801                             } else {
00802                                 timeout = 0;
00803                             }
00804                         } while ((send < got ) && (retcode >= 0) && (timeout < 200));
00805                         if (retcode <= 0) {
00806 #ifdef FTPD_DEBUG
00807                             printf("Error in NutTcpSend\n");
00808 #endif
00809                             ec = 551;
00810                             break;
00811                         }
00812                     }
00813                 }
00814 
00815                 
00816                 else {
00817                     while ((got = NutTcpReceive(sock, buf, mss)) > 0) {
00818                         int x;
00819                         if ((x = _write(fh, buf, got)) != got) {
00820                             ec = 552;
00821                             break;
00822                         }
00823                     }
00824                 }
00825                 free(buf);
00826             }
00827             NutTcpCloseSocket(sock);
00828         }
00829 #ifdef FTPD_DEBUG
00830           else {
00831           puts_P(dataconnectfailed_P);
00832         }
00833 #endif
00834         _close(fh);
00835 
00836         
00837         if (mode == 0 && ec) {
00838             unlink(path);
00839         }
00840     }
00841     if (ec) {
00842         return NutFtpRespondBad(session, ec);
00843     }
00844     return NutFtpRespondOk(session, 226);
00845 }
00846 
00860 int NutFtpTransferDirectoryOptions(FTPSESSION * session, char *path, int options)
00861 {
00862     static prog_char fileattributes_P[] = "rw-rw-rw-  1 0 0 %6lu ";
00863     static prog_char dateattribute_P[] = "%.3s %u ";
00864     static prog_char timeattribute_P[] = "%02u:%02u ";
00865     TCPSOCKET *sock;
00866     FILE *fp;
00867 
00868     struct stat st;
00869     DIR *dir;
00870     struct dirent *d_ent;
00871     tm *gmt;
00872     uint32_t size;
00873     int ec = 550;
00874     char *name;
00875     size_t pathlen;
00876 
00877     dir = opendir(path);
00878     if (dir) {
00879         NutFtpSendMode(session, 0);
00880         if ((sock = NutFtpDataConnect(session)) != 0) {
00881             if ((fp = _fdopen((int) sock, "r+b")) != 0) {
00882                 ec = 0;
00883                 pathlen = strlen(path);
00884                 while ((d_ent = readdir(dir)) != 0) {
00885                     if ((d_ent->d_name[0] == '.')  && ((options & 1) == 0)) {
00886                         continue;
00887                     }
00888                     if ((name = malloc(pathlen + strlen(d_ent->d_name) + 2)) != 0) {
00889                         strcpy(name, path);
00890                         if (pathlen == 0 || name[pathlen - 1] != '/') {
00891                             strcat(name, "/");
00892                         }
00893                         strcat(name, d_ent->d_name);
00894                         if (stat(name, &st) == 0) {
00895                             if (S_ISDIR(st.st_mode)) {
00896                                 fputc('d', fp);
00897                                 size = 0;
00898                             } else {
00899                                 fputc('-', fp);
00900                                 size = st.st_size;
00901                             }
00902                             fprintf_P(fp, fileattributes_P, size);
00903                             gmt = gmtime(&st.st_mtime);
00904                             
00905                             fprintf_P(fp, dateattribute_P, mon_name + gmt->tm_mon * 3, gmt->tm_mday);
00906                             
00907                             fprintf_P(fp, timeattribute_P, gmt->tm_hour, gmt->tm_min);
00908                             fputs(d_ent->d_name, fp);
00909                             fputs("\r\n", fp);
00910                         }
00911                         free(name);
00912                     }
00913                 }
00914                 fclose(fp);
00915             }
00916             NutTcpCloseSocket(sock);
00917         }
00918         closedir(dir);
00919     }
00920     if (ec) {
00921         return NutFtpRespondBad(session, ec);
00922     }
00923     return NutFtpRespondOk(session, 226);
00924 }
00925 
00938 int NutFtpTransferDirectory(FTPSESSION * session, char *path)
00939 {
00940     return NutFtpTransferDirectoryOptions(session, path, 0);
00941 }
00942 
00955 int NutFtpProcessMkd(FTPSESSION * session, char *path)
00956 {
00957     if (mkdir(path, 0777)) {
00958         return NutFtpRespondBad(session, 550);
00959     }
00960     return NutFtpRespondOk(session, 257);
00961 }
00962 
00963 
00964 int NutFtpRenamePrepare(FTPSESSION * session, char *path)
00965 {
00966     if (session->ftp_renamesource) {
00967         free(session->ftp_renamesource);
00968         session->ftp_renamesource = NULL;
00969     }
00970     if (path) {
00971         struct stat st;
00972         if (stat(path, &st) == 0) {
00973             session->ftp_renamesource = strdup(path);
00974             if (session->ftp_renamesource) {
00975                 return NutFtpRespondOk(session, 350);
00976             }
00977         } else {
00978           return NutFtpRespondBad(session, 450);
00979         }
00980     }
00981     return NutFtpRespondBad(session, 501);
00982 }
00983 
00984 int NutFtpRenameAction(FTPSESSION * session, char *path)
00985 {
00986     uint16_t responsebad;
00987     if (session->ftp_renamesource) {
00988          if (path) {
00989              int res = rename(session->ftp_renamesource, path);
00990              free(session->ftp_renamesource);
00991              session->ftp_renamesource = NULL;
00992              if (res == 0) {
00993                  return NutFtpRespondOk(session, 250);
00994              } else {
00995                  responsebad = 550;
00996              }
00997          } else {
00998              responsebad = 501;
00999          }
01000     } else {
01001          responsebad = 503;
01002     }
01003     return NutFtpRespondBad(session, responsebad);
01004 }
01005 
01006 
01019 int NutFtpProcessPass(FTPSESSION * session, char *pass)
01020 {
01021     if (ftp_pass && *ftp_pass) {
01022         if (session->ftp_login != 1 || strcmp(ftp_pass, pass)) {
01023             session->ftp_login = 0;
01024             return NutFtpRespondBad(session, 550);
01025         }
01026     }
01027     session->ftp_login = 2;
01028     return NutFtpRespondOk(session, 230);
01029 }
01030 
01044 int NutFtpProcessPassiv(FTPSESSION * session)
01045 {
01046     static prog_char passiveprint_P[] = "227 Passive (%u,%u,%u,%u,%u,%u).\r\n";
01047     uint32_t ip = session->ftp_sock->so_local_addr;
01048     uint16_t port = 20;
01049 
01050     fprintf_P(session->ftp_stream, passiveprint_P,        
01051             (uint8_t) ip, (uint8_t) (ip >> 8), (uint8_t) (ip >> 16), (uint8_t) (ip >> 24),  
01052             (uint8_t) (port >> 8), (uint8_t) port);
01053     fflush(session->ftp_stream);
01054     session->ftp_passive = 1;
01055 
01056     return 0;
01057 }
01058 
01073 int NutFtpProcessPort(FTPSESSION * session, char *args)
01074 {
01075     if (ParseIpPort(args, &session->ftp_data_ip, &session->ftp_data_port) == 6) {
01076         if (session->ftp_sock->so_remote_addr == session->ftp_data_ip) {
01077             return NutFtpRespondOk(session, 200);
01078         }
01079         return NutFtpRespondBad(session, 425);
01080     }
01081     return NutFtpRespondBad(session, 501);;
01082 }
01083 
01096 int NutFtpProcessPwd(FTPSESSION * session)
01097 {
01098     static prog_char pwdanswer_P[] = "257 \"%s\"\r\n";
01099 #ifdef FTPD_DEBUG
01100     printf("\n<'257 \"%s\"' ", session->ftp_cwd);
01101 #endif
01102     fprintf_P(session->ftp_stream, pwdanswer_P, session->ftp_cwd);
01103     return 0;
01104 }
01105 
01118 int NutFtpProcessRmd(FTPSESSION * session, char *path)
01119 {
01120     if (rmdir(path)) {
01121         return NutFtpRespondBad(session, 451);
01122     }
01123     return NutFtpRespondOk(session, 257);
01124 }
01125 
01135 int NutFtpProcessSystem(FTPSESSION * session)
01136 {
01137     static prog_char unixtype_P[] = "215 UNIX Type: L8\r\n";
01138 #ifdef FTPD_DEBUG
01139     printf("\n<'215 UNIX Type: L8' ");
01140 #endif
01141     fputs_P(unixtype_P, session->ftp_stream);
01142     return 0;
01143 }
01144 
01159 int NutFtpProcessType(FTPSESSION * session, char *typecode)
01160 {
01161     session->ftp_tran_mode = (*typecode != 'A') && (*typecode != 'a');
01162     return NutFtpRespondOk(session, 200);
01163 }
01164 
01177 int NutFtpProcessUser(FTPSESSION * session, char *user)
01178 {
01179     if (ftp_user && *ftp_user) {
01180         if (session->ftp_login && strcmp(ftp_user, user)) {
01181             session->ftp_login = 0;
01182             return NutFtpRespondBad(session, 550);
01183         }
01184     }
01185 
01186     
01187     if (ftp_pass && *ftp_pass) {
01188         session->ftp_login = 1;
01189         return NutFtpRespondOk(session, 331);
01190     }
01191 
01192     
01193     session->ftp_login = 2;
01194     return NutFtpRespondOk(session, 230);
01195 }
01196 
01208 int NutFtpProcessRequest(FTPSESSION * session, char *request)
01209 {
01210     int rc = 0;
01211     char *cmd;
01212     char *args;
01213 
01214     
01215     SplitCmdArg(request, &cmd, &args);
01216 #ifdef FTPD_DEBUG
01217     printf("\n>'%s %s' ", cmd, args);
01218 #endif
01219 
01220     
01221     if ((session->ftp_renamesource) && (strcmp_P(cmd, cmd_rename2_P))) {
01222           free(session->ftp_renamesource);
01223           session->ftp_renamesource = NULL;
01224     }
01225     
01226     if (strcmp_P(cmd, cmd_quit_P) == 0) {
01227         NutFtpRespondOk(session, 221);
01228         rc = -1;
01229     }
01230     
01231     else if (strcmp_P(cmd, cmd_user_P) == 0) {
01232         rc = NutFtpProcessUser(session, args);
01233     }
01234 
01235     
01236     else if (strcmp_P(cmd, cmd_pass_P) == 0) {
01237         rc = NutFtpProcessPass(session, args);
01238     } else if (strcmp_P(cmd, cmd_noop_P) == 0) {
01239         NutFtpRespondOk(session, 200);
01240     }
01241     
01242     else if (session->ftp_login < 2) {
01243         rc = NutFtpRespondBad(session, 530);
01244     }
01245 
01246     
01247     else {
01248 
01249         
01250         if (strcmp_P(cmd, cmd_pasv_P) == 0) {
01251             rc = NutFtpProcessPassiv(session);
01252         }
01253 
01254         
01255         else if (strcmp_P(cmd, cmd_port_P) == 0) {
01256             rc = NutFtpProcessPort(session, args);
01257         }
01258 
01259         
01260         else if (strcmp_P(cmd, cmd_pwd_P) == 0 || strcmp_P(cmd, cmd_xpwd_P) == 0) {
01261             rc = NutFtpProcessPwd(session);
01262         }
01263 
01264         
01265         else if (strcmp_P(cmd, cmd_syst_P) == 0) {
01266             rc = NutFtpProcessSystem(session);
01267         }
01268 
01269         
01270         else if (strcmp_P(cmd, cmd_type_P) == 0) {
01271             rc = NutFtpProcessType(session, args);
01272         }
01273         
01274         else {
01275             char *path;
01276             char *argsredux = args;
01277             int options = 0;
01278             if (args[0] == '-') {
01279                  if (strchr(args, 'a')) {
01280                    options = 1;
01281                  }
01282                  argsredux = strchr(args, ' ');
01283                  if ((argsredux) && (strlen(argsredux) > 0)) {
01284                      argsredux++; 
01285                  } else {
01286                      argsredux = "";
01287                  }
01288             }
01289             if ((path = CreateFullPathName(ftp_root, session->ftp_cwd, argsredux)) == 0) {
01290                 rc = NutFtpRespondBad(session, 451);
01291             }
01292 
01293             
01294             else if (strcmp_P(cmd, cmd_cwd_P) == 0) {
01295                 rc = NutFtpProcessCwd(session, path);
01296             }
01297 
01298             
01299             else if (strcmp_P(cmd, cmd_dele_P) == 0) {
01300                 rc = NutFtpProcessDelete(session, path);
01301             }
01302 
01303             
01304             else if (strcmp_P(cmd, cmd_list_P) == 0 || strcmp_P(cmd, cmd_nlst_P) == 0) {
01305                 rc = NutFtpTransferDirectoryOptions(session, path, options);
01306             }
01307 
01308             
01309             else if (strcmp_P(cmd, cmd_mkd_P) == 0 || strcmp_P(cmd, cmd_xmkd_P) == 0) {
01310                 rc = NutFtpProcessMkd(session, path);
01311             }
01312 
01313             
01314             else if (strcmp_P(cmd, cmd_retr_P) == 0) {
01315                 rc = NutFtpTransferFile(session, path, 1);
01316             }
01317 
01318             
01319             else if (strcmp_P(cmd, cmd_rmd_P) == 0 || strcmp_P(cmd, cmd_xrmd_P) == 0) {
01320                 rc = NutFtpProcessRmd(session, path);
01321             }
01322 
01323             
01324             else if (strcmp_P(cmd, cmd_stor_P) == 0) {
01325                 rc = NutFtpTransferFile(session, path, 0);
01326             }
01327             
01328             else if (strcmp_P(cmd, cmd_rename1_P) == 0) {
01329                 rc = NutFtpRenamePrepare(session, path);
01330             }
01331             
01332             else if (strcmp_P(cmd, cmd_rename2_P) == 0) {
01333                 rc = NutFtpRenameAction(session, path);
01334             }
01335             
01336             else {
01337                 rc = NutFtpRespondBad(session, 502);
01338             }
01339 
01340             if (path) {
01341                 free(path);
01342             }
01343         }
01344     }
01345     return rc;
01346 }
01347 
01363 int NutFtpServerSession(TCPSOCKET * sock)
01364 {
01365     int rc = 0;
01366     FTPSESSION *session;
01367     char *buff;
01368     time_t now;
01369     struct _tm *tip;
01370     char ch;
01371 
01372     
01373     if (NutRegisterFtpRoot(ftp_root)) {
01374         return -1;
01375     }
01376 
01377     
01378     if ((buff = malloc(FTP_MAX_CMDBUF)) == 0) {
01379         return -1;
01380     }
01381 
01382     
01383     if ((session = NutFtpOpenSession(sock)) == 0) {
01384         free(buff);
01385         return -1;
01386     }
01387 
01388     
01389     time(&now);
01390     tip = localtime(&now);
01391 #ifdef FTPD_DEBUG
01392     printf("\n<'");
01393     printf_P(rep_banner, NutVersionString(), &mon_name[tip->tm_mon * 3],        
01394              tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01395 #endif
01396     fprintf_P(session->ftp_stream, rep_banner, NutVersionString(),      
01397               &mon_name[tip->tm_mon * 3],       
01398               tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01399 
01400     
01401 
01402 
01403     while (rc == 0) {
01404 
01405         
01406         fflush(session->ftp_stream);
01407         if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01408             rc = -1;
01409             break;
01410         }
01411 
01412         
01413         if ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r') {
01414             do {
01415                 if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01416                     rc = -1;
01417                     break;
01418                 }
01419             } while ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r');
01420             if (rc == 0) {
01421                 rc = NutFtpRespondBad(session, 500);
01422             }
01423         }
01424 
01425         
01426         else {
01427             rc = NutFtpProcessRequest(session, buff);
01428         }
01429     }
01430 
01431     
01432     NutFtpCloseSession(session);
01433     free(buff);
01434     return rc;
01435 }
01436