/* FTP Directory List Functions
$Revision: 1.3 $
$Date: 2002/06/24 04:04:32 $
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "ftp.h"
#include "rc.h"
#include "text.h"
#include "quftp.h"
int ftp_list(struct ftpconnection *connection, char *params, char showthem) {
char *buffer = NULL;
int response = 0, index = 0;
char *outputformat = NULL;
if (!ftp_check_ready(connection, 1)) return -1;
ftp_sendline(connection, "TYPE A\r\n"); // Go to ASCII mode
ftp_getrc(connection, NULL, 0, 0);
buffer = config(connection->variables, "passive");
if (!buffer || strcasecmp(buffer, "true") == 0)
response = ftp_open_data_pasv(connection, NULL, 0);
else response = ftp_open_data(connection);
if (response) {
log(LOG_ALERT, "ftp_list: bad response from ftp_open_data (%d)\n",
response);
return -response; // Can't open a data connection
}
if (params && *params) {
buffer = (char *)malloc(MAX_LINE_SIZE);
sprintf(buffer, "LIST %s\r\n", params);
ftp_sendline(connection, buffer);
free(buffer);
} else ftp_sendline(connection, "LIST\r\n");
response = ftp_getrc(connection, NULL, 0, 0);
switch (response) {
case 125 : /* Already a data connection */
break;
case 150 : ftp_wait_data(connection); /* Wait for the data connection */
break;
case 250 :
case 226 : log(LOG_INFO, "No files available\n");
return response;
break;
case 425 :
case 426 :
case 451 :
case 450 : log(LOG_ALERT, "Could not list directory\n");
return response;
break;
case 421 : log(LOG_ALERT, "Service unavailable\n");
ftp_disconnect(connection);
return response;
break;
case 500 : log(LOG_ALERT, "Server doesn't understand LIST\n");
return response;
break;
case 501 : log(LOG_ALERT, "Server doesn't understand LIST parameters\n");
return response;
break;
case 502 : log(LOG_ALERT, "Server doesn't understand LIST\n");
return response;
break;
case 530 : log(LOG_ALERT, "Not logged in\n");
return 0;
break;
default : log(LOG_ALERT, "Unknown response to LIST: %d\n", response);
return response;
break;
}
log(LOG_MESSAGE, "ftp_list: processing list\n");
buffer = (char *)malloc(4096);
outputformat = config(connection->variables, "lsformat");
while (1) {
char *temp;
memset(buffer, 0, 4096);
if ((response = ftp_read_data_line(connection, buffer, 4096))
== 0) break; /* Read Line */
if (strlen(buffer) == 0) continue; /* Got crap? */
if (ftp_parse_permissions(buffer) < 0) continue;
/* Parse -rw-r--r-- etc */
temp = strchr(buffer, '\n');
if (temp) *temp = 0;
if (showthem) {
if (outputformat && *outputformat)
printf("%s\n", listoutput(buffer, outputformat));
else
printf("%s\n", buffer);
}
index++; /* Keep a count of files */
}
free(buffer);
ftp_close_data(connection); /* Close the data connection */
response = ftp_getrc(connection, NULL, 0, 0); /* Server says ok? */
return index;
}
int ftp_nlst(struct ftpconnection *connection, char *params, char *list[], int max_items) {
char *buffer;
int index, response;
if (!ftp_check_ready(connection, 0)) return -1;
if (max_items > 0) memset(list, 0, sizeof(*list) * max_items);
ftp_sendline(connection, "TYPE A\r\n");
ftp_getrc(connection, NULL, 0, 0);
buffer = config(connection->variables, "passive");
if (!buffer || strcasecmp(buffer, "true") == 0)
response = ftp_open_data_pasv(connection, NULL, 0);
else response = ftp_open_data(connection);
index = 0;
if (params && *params) {
buffer = (char *)malloc(MAX_LINE_SIZE);
sprintf(buffer, "NLST %s\r\n", params);
ftp_sendline(connection, buffer);
free(buffer);
} else ftp_sendline(connection, "NLST\r\n");
response = ftp_getrc(connection, NULL, 0, 0);
switch (response) {
case 125 : /* Already a data connection */
break;
case 150 : ftp_wait_data(connection); /* Wait for the data connection */
break;
case 250 :
case 226 : printf("No files available\n");
connection->status = STATUS_IDLE;
return response;
break;
case 425 :
case 426 :
case 451 :
case 450 : log(LOG_ALERT, "Could not list directory\n");
connection->status = STATUS_IDLE;
return response;
break;
case 421 : log(LOG_ALERT, "Service unavailable\n");
ftp_disconnect(connection);
return response;
break;
case 500 : log(LOG_ALERT, "Server doesn't understand NLST\n");
connection->status = STATUS_IDLE;
return response;
break;
case 501 : log(LOG_ALERT, "Server doesn't understand NLST parameters\n");
connection->status = STATUS_IDLE;
return response;
break;
case 502 : log(LOG_ALERT, "Server doesn't understand NLST\n");
connection->status = STATUS_IDLE;
return response;
break;
case 530 : log(LOG_ALERT, "Not logged in\n");
ftp_disconnect(connection);
return 0;
break;
case 550 : /* log(LOG_ALERT, "No files found matching %s\n", params); */
connection->status = STATUS_IDLE;
return 0;
break;
default : log(LOG_ALERT, "Unknown response to NLST: %d\n", response);
connection->status = STATUS_IDLE;
return response;
break;
}
buffer = (char *)malloc(4096);
while ((response = ftp_read_data_line(connection, buffer, 4096) > 0)) {
if (strlen(buffer) == 0) continue;
if (strcmp(buffer, ".") == 0) continue;
if (strcmp(buffer, "..") == 0) continue;
if (max_items > 0) list[index] = strdup(buffer);
index++;
if (max_items > 0) if (index > max_items) break;
}
if (index >= max_items) index = max_items;
/* else for (temp = index; temp < max_items; temp++) list[temp] = 0; */
list[index] = NULL;
ftp_getrc(connection, NULL, 0, 0);
free(buffer);
ftp_close_data(connection);
return index;
}
char *listoutput(char *input, char *format) {
struct filedetails details;
int inputindex;
char output[MAX_LINE_SIZE], *temp;
strcpy(output, input);
if (ftp_split_ls(output, &details))
return NULL;
memset(output, 0, MAX_LINE_SIZE);
for (inputindex = 0; format[inputindex] != 0; inputindex++) {
if (format[inputindex] == '%') {
inputindex++;
switch (format[inputindex]) {
case '%' : sprintf(output, "%s%%", output);
break;
case 'f' : sprintf(output, "%s%s", output, details.filename);
break;
case 's' : sprintf(output, "%s%lu", output, details.size);
break;
case 't' : sprintf(output, "%s%s", output, asctime(&details.timestamp));
break;
case 'p' : temp = print_permissions(details.permissions);
sprintf(output, "%s%s", output, temp);
free(temp);
break;
case 'o' : sprintf(output, "%s%s", output, details.owner);
break;
case 'g' : sprintf(output, "%s%s", output, details.group);
break;
case 'l' : sprintf(output, "%s%d", output, details.links);
break;
}
} else
sprintf(output, "%s%c", output, format[inputindex]);
}
return strdup(output);
}
syntax highlighted by Code2HTML, v. 0.9.1