ftp.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:24k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/ftp.c 1.37 2000/03/20 18:47:14 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5e.
- Functions for getting URLs using FTP.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1997,98,99,2000 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <time.h>
- #include "wwwoffle.h"
- #include "misc.h"
- #include "config.h"
- #include "errors.h"
- #include "sockets.h"
- #include "proto.h"
- /*+ Set this to 1 to see the full dialog with the FTP server. +*/
- #define DEBUG_FTP 0
- /*+ Set to the name of the proxy if there is one. +*/
- static char *proxy=NULL;
- /*+ The file descriptor of the socket +*/
- static int server_ctrl=-1, /*+ for the control connection to the server. +*/
- server_data=-1; /*+ for the data connection to the server. +*/
- /*+ A buffer to contain the reply +*/
- static char *bufferhead=NULL, /*+ head. +*/
- *buffer=NULL, /*+ body. +*/
- *buffertail=NULL; /*+ tail. +*/
- /*+ The number of characters in the buffer +*/
- static int nbufferhead=0, /*+ in total for the head . +*/
- nreadhead=0, /*+ that have been read from the head. +*/
- nbuffer=0, /*+ in total for the body part. +*/
- nread=0, /*+ that have been read for the body. +*/
- nbuffertail=0, /*+ in total for the tail . +*/
- nreadtail=0; /*+ that have been read from the tail. +*/
- static char *htmlise_dir_entry(char *line);
- /*++++++++++++++++++++++++++++++++++++++
- Open a connection to get a URL using FTP.
- char *FTP_Open Returns NULL on success, a useful message on error.
- URL *Url The URL to open.
- ++++++++++++++++++++++++++++++++++++++*/
- char *FTP_Open(URL *Url)
- {
- char *msg=NULL;
- char *colon;
- char *server_host=NULL;
- int server_port=Protocols[Protocol_FTP].defport;
- /* Sort out the host. */
- proxy=WhichProxy(Url->proto,Url->host);
- if(IsLocalNetHost(Url->host))
- proxy=NULL;
- if(proxy)
- {
- server_host=(char*)malloc(strlen(proxy)+1);
- strcpy(server_host,proxy);
- }
- else
- {
- server_host=(char*)malloc(strlen(Url->host)+1);
- strcpy(server_host,Url->host);
- }
- if((colon=strchr(server_host,':')))
- {
- *colon++=0;
- if(*colon)
- server_port=atoi(colon);
- }
- /* Open the connection. */
- server_ctrl=OpenClientSocket(server_host,server_port,ConnectTimeout);
- init_buffer(server_ctrl);
- if(server_ctrl==-1)
- msg=PrintMessage(Warning,"Cannot open the FTP control connection to %s port %d; [%!s].",server_host,server_port);
- free(server_host);
- return(msg);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Write to the server to request the URL.
- char *FTP_Request Returns NULL on success, a useful message on error.
- URL *Url The URL to get.
- Header *request_head The head of the HTTP request for the URL.
- Body *request_body The body of the HTTP request for the URL.
- ++++++++++++++++++++++++++++++++++++++*/
- char *FTP_Request(URL *Url,Header *request_head,Body *request_body)
- {
- char *msg=NULL,*str=NULL;
- char *path,*file=NULL;
- char *host,*mimetype=NULL;
- char *msg_reply=NULL;
- char *timestamp,sizebuf[32];
- int i,l,port_l,port_h;
- struct tm modtime;
- time_t mtime;
- char *user,*pass;
- /* Initial setting up. */
- sizebuf[0]=0;
- time(&mtime);
- modtime=*gmtime(&mtime);
- /* Take a simple route if it is proxied. */
- if(proxy)
- {
- char *head;
- MakeRequestAuthorised(proxy,request_head);
- head=HeaderString(request_head);
- PrintMessage(ExtraDebug,"Outgoing Request Head (to proxy)n%s",head);
- if(write_string(server_ctrl,head)==-1)
- msg=PrintMessage(Warning,"Failed to write to remote FTP proxy [%!s].");
- if(request_body && write_data(server_ctrl,request_body->content,request_body->length)==-1)
- msg=PrintMessage(Warning,"Failed to write to remote FTP proxy [%!s].");
- free(head);
- return(msg);
- }
- /* Else Sort out the path. */
- path=URLDecode(Url->path,0);
- if(path[strlen(path)-1]=='/')
- {
- path[strlen(path)-1]=0;
- file=NULL;
- }
- else
- for(i=strlen(path)-1;i>=0;i--)
- if(path[i]=='/')
- {
- path[i]=0;
- file=&path[i+1];
- break;
- }
- if(Url->user)
- {
- user=Url->user;
- pass=Url->pass;
- }
- else
- WhatFTPUserPass(Url->host,&user,&pass);
- /* send all the RFC959 commands. */
- server_data=-1;
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: connected; got: %s",str);
- if(!file && !*path && str && isdigit(str[0]) && isdigit(str[1]) && isdigit(str[2]) && str[3]=='-')
- {
- if(msg_reply)
- {
- msg_reply=(char*)realloc((void*)msg_reply,strlen(msg_reply)+strlen(str));
- strcat(msg_reply,str+4);
- }
- else
- {
- msg_reply=(char*)malloc(strlen(str));
- strcpy(msg_reply,str+4);
- }
- }
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || atoi(str)!=220)
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message when connected to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server when connected; timed out?");
- return(msg);
- }
- /* Login */
- if(write_formatted(server_ctrl,"USER %srn",user)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'USER' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'USER %s'; got: %s",user,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || (atoi(str)!=230 && atoi(str)!=331))
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'USER' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'USER' command; timed out?");
- return(msg);
- }
- if(atoi(str)==331)
- {
- if(write_formatted(server_ctrl,"PASS %srn",pass)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'PASS' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'PASS %s'; got: %s",pass,str);
- if(!file && !*path && str && isdigit(str[0]) && isdigit(str[1]) && isdigit(str[2]) && str[3]=='-')
- {
- if(msg_reply)
- {
- msg_reply=(char*)realloc((void*)msg_reply,strlen(msg_reply)+strlen(str));
- strcat(msg_reply,str+4);
- }
- else
- {
- msg_reply=(char*)malloc(strlen(str));
- strcpy(msg_reply,str+4);
- }
- }
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || (atoi(str)!=202 && atoi(str)!=230))
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'PASS' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'PASS' command; timed out?");
- return(msg);
- }
- }
- /* Change directory */
- if(write_formatted(server_ctrl,"CWD %srn",*path?path:"/")==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'CWD' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'CWD %s' got: %s",*path?path:"/",str);
- if(!file && str && isdigit(str[0]) && isdigit(str[1]) && isdigit(str[2]) && str[3]=='-')
- {
- if(msg_reply)
- {
- msg_reply=(char*)realloc((void*)msg_reply,strlen(msg_reply)+strlen(str));
- strcat(msg_reply,str+4);
- }
- else
- {
- msg_reply=(char*)malloc(strlen(str));
- strcpy(msg_reply,str+4);
- }
- }
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || atoi(str)!=250)
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'CWD' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'CWD' command; timed out?");
- return(msg);
- }
- /* Change directory again to see if file is a dir. */
- if(file)
- {
- if(write_formatted(server_ctrl,"CWD %srn",file)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'CWD' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'CWD %s' got: %s",file,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || (atoi(str)!=250 && atoi(str)!=501 && atoi(str)!=530 && atoi(str)!=550))
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'CWD' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'CWD' command; timed out?");
- return(msg);
- }
- if(atoi(str)==250)
- {
- char *loc=(char*)malloc(strlen(Url->link)+2);
- strcpy(loc,Url->link);
- strcat(loc,"/");
- bufferhead=HTMLMessageHead(-1,302,"Is a directory",
- "Location",loc,
- NULL);
- buffer=HTMLMessageBody(-1,"FTPDirRedirect",
- "url",Url->link,
- NULL);
- free(loc);
- goto near_end;
- }
- }
- /* Set mode to binary or ASCII */
- if(write_formatted(server_ctrl,"TYPE %crn",file?'I':'A')==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'TYPE' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'TYPE %c'; got: %s",file?'I':'A',str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || atoi(str)!=200)
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'TYPE' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'TYPE' command; timed out?");
- return(msg);
- }
- if(!strcmp(request_head->method,"GET"))
- {
- /* Try and get the size and modification time. */
- if(file)
- {
- if(write_formatted(server_ctrl,"SIZE %srn",file)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'SIZE' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'SIZE %s'; got: %s",file,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if (atoi(str) == 213)
- if (str[4])
- sprintf(sizebuf, "%ld", (long)atoi(str+4));
- if(write_formatted(server_ctrl,"MDTM %srn",file)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'MDTM' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'MDTM %s'; got: %s",file,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if (atoi(str) == 213)
- {
- int year, mon, mday, hour, min, sec;
- if (sscanf(str, "%*d %4d%2d%2d%2d%2d%2d", &year, &mon, &mday, &hour, &min, &sec) == 6)
- {
- memset(&modtime, 0, sizeof(modtime));
- modtime.tm_year = year - 1900;
- modtime.tm_mon = mon - 1;
- modtime.tm_mday = mday;
- modtime.tm_hour = hour;
- modtime.tm_min = min;
- modtime.tm_sec = sec;
- }
- }
- }
- }
- /* Create the data connection. */
- if(write_string(server_ctrl,"PASVrn")==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'PASV' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'PASV'; got: %s",str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- if(!str || atoi(str)!=227)
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'PASV' command",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'PASV' command; timed out?");
- return(msg);
- }
- if((host=strchr(str,',')))
- {
- while(isdigit(*--host));
- host++;
- }
- if(!host || sscanf(host,"%*d,%*d,%*d,%*d%n,%d,%d",&l,&port_h,&port_l)!=2)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'PASV' command, cannot parse.",str);
- return(msg);
- }
- host[l]=0;
- for(;l>0;l--)
- if(host[l]==',')
- host[l]='.';
- server_data=OpenClientSocket(host,port_l+256*port_h,ConnectTimeout);
- init_buffer(server_data);
- if(server_data==-1)
- {
- msg=PrintMessage(Warning,"Cannot open the FTP data connection [%!s].");
- return(msg);
- }
- /* Make the request */
- if(!strcmp(request_head->method,"GET"))
- {
- if(file)
- {
- if(write_formatted(server_ctrl,"RETR %srn",file)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'RETR' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'RETR %s'; got: %s",file,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- mimetype=WhatMIMEType(file);
- }
- else
- {
- if(write_string(server_ctrl,"LIST -arn")==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'LIST -a' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'LIST -a'; got: %s",str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- mimetype="text/html";
- }
- if(str && (atoi(str)==150 || atoi(str)==125))
- {
- char *p=str;
- while(*p!='r' && *p!='n')
- p++;
- *p=0;
- }
- else
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending '%s' command to FTP server.",str,file?"RETR":"LIST -a");
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to '%s' command; timed out?",file?"RETR":"LIST -a");
- return(msg);
- }
- }
- else if(file) /* PUT */
- {
- if(file)
- {
- if(write_formatted(server_ctrl,"STOR %srn",file)==-1)
- {
- msg=PrintMessage(Warning,"Failed to write 'STOR' command to remote FTP host [%!s].");
- return(msg);
- }
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'STOR %s'; got: %s",file,str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- mimetype="text/html";
- }
- else
- {
- msg=PrintMessage(Warning,"Cannot use the PUT method on a directory name");
- return(msg);
- }
- if(str && (atoi(str)==150 || atoi(str)==125))
- {
- char *p=str;
- while(*p!='r' && *p!='n')
- p++;
- *p=0;
- }
- else
- {
- if(str)
- {
- char *p=str+strlen(str)-1;
- while(*p=='n' || *p=='r') *p--=0;
- msg=PrintMessage(Warning,"Got '%s' message after sending 'STOR' command to FTP server.",str);
- }
- else
- msg=PrintMessage(Warning,"No reply from FTP server to 'STOR' command; timed out?");
- return(msg);
- }
- write_data(server_data,request_body->content,request_body->length);
- }
- /* Prepare the HTTP header. */
- if(!strcmp(request_head->method,"GET"))
- {
- mtime=mktime(&modtime);
- if(mtime!=-1)
- timestamp=RFC822Date(mtime,1);
- else
- timestamp=RFC822Date(time(NULL),1);
-
- if(*sizebuf)
- bufferhead=HTMLMessageHead(-1,200,str+4,
- "Content-Type",mimetype,
- "Last-Modified",timestamp,
- "Content-Length",sizebuf,
- NULL);
- else
- bufferhead=HTMLMessageHead(-1,200,str+4,
- "Content-Type",mimetype,
- "Last-Modified",timestamp,
- NULL);
- }
- else
- {
- bufferhead=HTMLMessageHead(-1,200,str+4,
- "Content-Type",mimetype,
- NULL);
- }
- buffer=NULL;
- buffertail=NULL;
- if(!strcmp(request_head->method,"GET"))
- {
- if(!file)
- {
- if(msg_reply)
- {
- char *old_msg_reply=msg_reply;
- msg_reply=HTMLString(msg_reply);
- free(old_msg_reply);
- }
- buffer=HTMLMessageBody(-1,"FTPDir-Head",
- "url",URLDecode(Url->name,0),
- "message",msg_reply,
- NULL);
- buffertail=HTMLMessageBody(-1,"FTPDir-Tail",
- NULL);
- }
- }
- else
- {
- buffer=HTMLMessageBody(-1,"FTPPut",
- "url",URLDecode(Url->name,0),
- NULL);
- }
- near_end:
- if(msg_reply)
- free(msg_reply);
- nbufferhead=strlen(bufferhead); nreadhead=0;
- nbuffer=buffer?strlen(buffer):0; nread=0;
- nbuffertail=buffertail?strlen(buffertail):0; nreadtail=0;
- free(str);
- free(path);
- return(msg);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read a line from the header of the reply for the URL.
- char *FTP_ReadHead Returns the next line of data, NULL on EOF.
- char *line The previous line read.
- ++++++++++++++++++++++++++++++++++++++*/
- char *FTP_ReadHead(char *line)
- {
- char *l=line;
- int m;
- /* Take a simple route if it is proxied. */
- if(proxy)
- return(read_line_or_timeout(server_ctrl,line,SocketTimeout));
-
- /* Else send the header. */
- if(nreadhead==nbufferhead)
- return(NULL);
- for(m=nreadhead;m<nbufferhead;m++)
- if(bufferhead[m]=='n')
- break;
- m++;
- l=(char*)realloc((void*)l,m-nreadhead+1);
- strncpy(l,&bufferhead[nreadhead],m-nreadhead);
- l[m-nreadhead]=0;
- nreadhead=m;
- return(l);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read bytes from the body of the reply for the URL.
- int FTP_ReadBody Returns the number of bytes read on success, -1 on error.
- char *s A string to fill in with the information.
- int n The number of bytes to read.
- ++++++++++++++++++++++++++++++++++++++*/
- int FTP_ReadBody(char *s,int n)
- {
- int m=0;
- /* Take a simple route if it is proxied. */
- if(proxy)
- return(read_data_or_timeout(server_ctrl,s,n,SocketTimeout));
-
- /* Else send the data then the tail. */
- if(server_data==-1) /* Redirection */
- {
- for(;nread<nbuffer && m<n;nread++,m++)
- s[m]=buffer[nread];
- for(;nreadtail<nbuffertail && m<n;nreadtail++,m++)
- s[m]=buffertail[nreadtail];
- }
- else if(!buffer && !buffertail) /* File not dir entry. */
- m=read_data_or_timeout(server_data,s,n,SocketTimeout);
- else if(buffer && buffertail) /* Middle of dir entry */
- {
- for(;nread<nbuffer && m<n;nread++,m++)
- s[m]=buffer[nread];
- if(nread==nbuffer)
- {
- buffer=htmlise_dir_entry(buffer);
- if(buffer)
- nbuffer=strlen(buffer),nread=0;
- }
- if(!buffer)
- for(;nreadtail<nbuffertail && m<n;nreadtail++,m++)
- s[m]=buffertail[nreadtail];
- }
- else if(!buffer && buffertail) /* End of dir entry. */
- {
- for(;nreadtail<nbuffertail && m<n;nreadtail++,m++)
- s[m]=buffertail[nreadtail];
- }
- else /* if(buffer && !buffertail) */ /* Done a PUT */
- {
- for(;nread<nbuffer && m<n;nread++,m++)
- s[m]=buffer[nread];
- }
- return(m);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Close a connection opened using FTP.
- int FTP_Close Return 0 on success, -1 on error.
- ++++++++++++++++++++++++++++++++++++++*/
- int FTP_Close(void)
- {
- int err=0;
- char *str=NULL;
- /* Take a simple route if it is proxied. */
- if(proxy)
- return(CloseSocket(server_ctrl));
- /* Else say goodbye and close all of the sockets, */
- if(server_data!=-1)
- CloseSocket(server_data);
- write_string(server_ctrl,"QUITrn");
- do
- {
- str=read_line_or_timeout(server_ctrl,str,SocketTimeout);
- PrintMessage(ExtraDebug,"FTP: sent 'QUIT'; got: %s",str);
- }
- while(str && (!isdigit(str[0]) || !isdigit(str[1]) || !isdigit(str[2]) || str[3]!=' '));
- err=CloseSocket(server_ctrl);
- if(bufferhead)
- free(bufferhead);
- if(buffer)
- free(buffer);
- if(buffertail)
- free(buffertail);
- return(err);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Convert a line from the ftp server dir listing into a pretty listing.
- char *htmlise_dir_entry Returns the next line.
- char *line The previous line.
- ++++++++++++++++++++++++++++++++++++++*/
- static char *htmlise_dir_entry(char *line)
- {
- int i,isdir=0,islink=0;
- char *q,*p[16],*l,*file=NULL,*link=NULL;
- l=read_line_or_timeout(server_data,line,SocketTimeout);
- if(!l)
- return(l);
- for(q=l,i=0;*q && i<16;i++)
- {
- while(*q==' ' || *q=='t')
- q++;
- if(*q=='n' || *q=='r')
- break;
- if(*q)
- p[i]=q;
- while(*q && *q!=' ' && *q!='t' && *q!='r' && *q!='n')
- q++;
- }
- if((*p[0]=='-' || *p[0]=='d' || *p[0]=='l') && i>=8) /* A UNIX 'ls -l' listing. */
- {
- if(i==8)
- {file=p[7]; link=file;}
- else if(i==10 && (*p[8]=='-' && *(p[8]+1)=='>'))
- {file=p[7]; link=p[9];}
- else if(i==9)
- {file=p[8]; link=file;}
- else if(i==11 && (*p[9]=='-' && *(p[9]+1)=='>'))
- {file=p[8]; link=p[10];}
- if(*p[0]=='d')
- isdir=1;
- if(*p[0]=='l')
- islink=1;
- }
- if(file)
- {
- char *endf,endfc,*endl,endlc,*ll,*fileurlenc,*linkurlenc;
- endf=file;
- while(*endf && *endf!=' ' && *endf!='t' && *endf!='r' && *endf!='n')
- endf++;
- endfc=*endf;
- endl=link;
- while(*endl && *endl!=' ' && *endl!='t' && *endl!='r' && *endl!='n')
- endl++;
- endlc=*endl;
- *endf=0;
- fileurlenc=URLEncode(file);
- *endf=endfc;
- *endl=0;
- linkurlenc=URLEncode(link);
- *endl=endlc;
- ll=(char*)malloc(strlen(l)+strlen(fileurlenc)+strlen(linkurlenc)+40);
- strncpy(ll,l,file-l);
- strcpy(ll+(file-l),"<a href="");
- strcat(ll,"./");
- strcat(ll,fileurlenc);
- if(isdir && *(endl-1)!='/')
- strcat(ll,"/");
- strcat(ll,"">");
- *endf=0;
- strcat(ll,file);
- *endf=endfc;
- strcat(ll,"</a>");
- if(islink)
- {
- strncat(ll,endf,link-endf);
- strcat(ll,"<a href="");
- if(strncmp(linkurlenc,"../",3) && strncmp(linkurlenc,"./",2) && strncmp(linkurlenc,"/",1))
- strcat(ll,"./");
- strcat(ll,linkurlenc);
- strcat(ll,"">");
- *endl=0;
- strcat(ll,link);
- *endl=endlc;
- strcat(ll,"</a>");
- strcat(ll,endl);
- }
- else
- {
- strcat(ll,endf);
- }
- free(fileurlenc);
- free(linkurlenc);
- if(l)
- free(l);
- l=ll;
- }
- return(l);
- }