⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netcam_ftp.c

📁 motion motion
💻 C
📖 第 1 页 / 共 2 页
字号:
/***      Much of the FTP code was inspired by the nanoftp.c module from*      libxml2 (Copyright Daniel Veillard, 2003).  The routines have been*      modified to fit the needs of the Motion project.**      Copyright 2005, William M. Brack*      This software is distributed under the GNU Public license Version 2.*      See also the file 'COPYING'.**/#include "motion.h"  /* needs to come first, because _GNU_SOURCE_ set there */#include <ctype.h>//#include <errno.h>//#include <fcntl.h>#include <netdb.h>#include <regex.h>//#include <stdarg.h>//#include <stdlib.h>//#include <stdio.h>//#include <string.h>//#include <syslog.h>//#include <unistd.h>#include <sys/socket.h>//#include <sys/stat.h>//#include <sys/types.h>#include <netinet/in.h>#include "netcam_ftp.h"/*** ftp_new_context**      Create a new FTP context structure** Parameters**       None** Returns:     Pointer to the newly-created structure, NULL if error**/ftp_context_pointer ftp_new_context(void){	ftp_context_pointer ret;	/* note that mymalloc will exit on any problem */	ret = mymalloc(sizeof(ftp_context));	memset(ret, 0, sizeof(ftp_context));	ret->control_file_desc = -1;                /* no control connection yet */	ret->data_file_desc = -1;                   /* no data connection yet */	return ret;}/*** ftp_free_context**      Free the resources allocated for this context** Parameters**      ctxt    Pointer to the ftp_context structure** Returns:     Nothing**/void ftp_free_context(ftp_context_pointer ctxt){	if (ctxt == NULL)		return;	if (ctxt->path != NULL)		free(ctxt->path);	if (ctxt->user)		free(ctxt->user);	if (ctxt->passwd)		free(ctxt->passwd);	if (ctxt->control_file_desc >= 0)		close(ctxt->control_file_desc);	free(ctxt);}/*** ftp_parse_response**      Parses the answer from the server, extracting the numeric code.** Parameters:**      buf     the buffer containing the response*      len     the buffer length** Returns:*     0 for errors*     +XXX for last line of response*     -XXX for response to be continued*/static int ftp_parse_response(char *buf, int len) {	int val = 0;	if (len < 3)		return(-1);	if ((*buf >= '0') && (*buf <= '9'))		val = val * 10 + (*buf - '0');	else		return(0);	buf++;	if ((*buf >= '0') && (*buf <= '9'))		val = val * 10 + (*buf - '0');	else		return(0);	buf++;	if ((*buf >= '0') && (*buf <= '9'))		val = val * 10 + (*buf - '0');	else		return(0);	buf++;	if (*buf == '-')		return(-val);	return(val);}/*** ftp_get_more**      Read more information from the FTP control connection** Parameters:**      ctxt    pointer to an FTP context** Returns the number of bytes read, < 0 indicates an error*/static int ftp_get_more(ftp_context_pointer ctxt) {	int len;	int size;	/* Validate that our context structure is valid */	if ((ctxt == NULL) || (ctxt->control_file_desc < 0))		return(-1);	if ((ctxt->control_buffer_index < 0) || (ctxt->control_buffer_index > FTP_BUF_SIZE))		return(-1);	if ((ctxt->control_buffer_used < 0) || (ctxt->control_buffer_used > FTP_BUF_SIZE))		return(-1);	if (ctxt->control_buffer_index > ctxt->control_buffer_used)		return(-1);	/*	* First pack the control buffer	*/	if (ctxt->control_buffer_index > 0) {		memmove(&ctxt->control_buffer[0],		&ctxt->control_buffer[ctxt->control_buffer_index],		ctxt->control_buffer_used - ctxt->control_buffer_index);		ctxt->control_buffer_used -= ctxt->control_buffer_index;		ctxt->control_buffer_index = 0;	}	size = FTP_BUF_SIZE - ctxt->control_buffer_used;	if (size == 0) {		return(0);	}	/*	* Read the amount left on the control connection	*/	if ((len = recv(ctxt->control_file_desc,	&ctxt->control_buffer[ctxt->control_buffer_index],	size, 0)) < 0) {		motion_log(LOG_ERR, 1, "recv failed in ftp_get_more");		close(ctxt->control_file_desc);		ctxt->control_file_desc = -1;		return(-1);	}	ctxt->control_buffer_used += len;	ctxt->control_buffer[ctxt->control_buffer_used] = 0;	return(len);}/*** ftp_get_response**      Read the response from the FTP server after a command.** Parameters**      ctxt    pointer to an FTP context** Returns the code number*/static int ftp_get_response(ftp_context_pointer ctxt) {	char *ptr, *end;	int len;	int res = -1, cur = -1;	if ((ctxt == NULL) || (ctxt->control_file_desc < 0))	return(-1);	get_more:	/*	* Assumes everything up to control_buffer[control_buffer_index] has been read	* and analyzed.	*/	len = ftp_get_more(ctxt);	if (len < 0) {		return(-1);	}	if ((ctxt->control_buffer_used == 0) && (len == 0)) {		return(-1);	}	ptr = &ctxt->control_buffer[ctxt->control_buffer_index];	end = &ctxt->control_buffer[ctxt->control_buffer_used];	while (ptr < end) {		cur = ftp_parse_response(ptr, end - ptr);		if (cur > 0) {			/*			* Successfully scanned the control code, skip			* till the end of the line, but keep the index to be			* able to analyze the result if needed.			*/			res = cur;			ptr += 3;			ctxt->control_buffer_answer = ptr - ctxt->control_buffer;			while ((ptr < end) && (*ptr != '\n')) ptr++;			if (*ptr == '\n') ptr++;			if (*ptr == '\r') ptr++;			break;		}		while ((ptr < end) && (*ptr != '\n'))		ptr++;		if (ptr >= end) {			ctxt->control_buffer_index = ctxt->control_buffer_used;			goto get_more;		}		if (*ptr != '\r') ptr++;	}	if (res < 0)	goto get_more;	ctxt->control_buffer_index = ptr - ctxt->control_buffer;	return(res / 100);}/*** Send the user authentication*/static int ftp_send_user(ftp_context_pointer ctxt) {	char buf[200];	int len;	int res;	if (ctxt->user == NULL)	snprintf(buf, sizeof(buf), "USER anonymous\r\n");	else	snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);	buf[sizeof(buf) - 1] = 0;	len = strlen(buf);	res = send(ctxt->control_file_desc, buf, len, 0);	if (res < 0) {		motion_log(LOG_ERR, 1, "send failed in ftp_send_user");		return(res);	}	return(0);}/*** Send the password authentication*/static int ftp_send_passwd(ftp_context_pointer ctxt) {	char buf[200];	int len;	int res;	if (ctxt->passwd == NULL)	snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");	else	snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);	buf[sizeof(buf) - 1] = 0;	len = strlen(buf);	res = send(ctxt->control_file_desc, buf, len, 0);	if (res < 0) {		motion_log(LOG_ERR, 1, "send failed in ftp_send_passwd");		return(res);	}	return(0);}/*** ftp_quit**      Send a QUIT command to the server** Parameters:**      ctxt    pointer to an FTP context** Returns -1 in case of error, 0 otherwise*/static int ftp_quit(ftp_context_pointer ctxt) {	char buf[200];	int len, res;	if ((ctxt == NULL) || (ctxt->control_file_desc < 0))	return(-1);	snprintf(buf, sizeof(buf), "QUIT\r\n");	len = strlen(buf);	res = send(ctxt->control_file_desc, buf, len, 0);	if (res < 0) {		motion_log(LOG_ERR, 1, "send failed in ftp_quit");		return(res);	}	return(0);}/*** ftp_connect**      Tries to open a control connection** Parameters:**      ctxt    an FTP context** Returns -1 in case of error, 0 otherwise*/int ftp_connect(netcam_context_ptr netcam) {	ftp_context_pointer ctxt;	struct hostent *hp;	int port;	int res;	int addrlen = sizeof (struct sockaddr_in);	if (netcam == NULL)	return -1;	ctxt = netcam->ftp;	if (ctxt == NULL)	return(-1);	if (netcam->connect_host == NULL)	return(-1);	/*	* do the blocking DNS query.	*/	port = netcam->connect_port;	if (port == 0)	port = 21;	memset (&ctxt->ftp_address, 0, sizeof(ctxt->ftp_address));	hp = gethostbyname (netcam->connect_host);	if (hp == NULL) {		motion_log(LOG_ERR, 1, "gethostbyname failed in ftp_connect");		return (-1);	}	if ((unsigned int) hp->h_length >	sizeof(((struct sockaddr_in *)&ctxt->ftp_address)->sin_addr)) {		motion_log(LOG_ERR, 1, "gethostbyname address mismatch "		"in ftp_connect");		return (-1);	}	/*	* Prepare the socket	*/	((struct sockaddr_in *)&ctxt->ftp_address)->sin_family = AF_INET;	memcpy (&((struct sockaddr_in *)&ctxt->ftp_address)->sin_addr,	hp->h_addr_list[0], hp->h_length);	((struct sockaddr_in *)&ctxt->ftp_address)->sin_port =	(u_short)htons ((unsigned short)port);	ctxt->control_file_desc = socket (AF_INET, SOCK_STREAM, 0);	addrlen = sizeof (struct sockaddr_in);	if (ctxt->control_file_desc < 0) {		motion_log(LOG_ERR, 1, "socket failed");		return(-1);	}	/*	* Do the connect.	*/	if (connect(ctxt->control_file_desc, (struct sockaddr *) &ctxt->ftp_address,	addrlen) < 0) {		motion_log(LOG_ERR, 1, "Failed to create a connection");		close(ctxt->control_file_desc);		ctxt->control_file_desc = -1;		return(-1);	}	/*	* Wait for the HELLO from the server.	*/	res = ftp_get_response(ctxt);	if (res != 2) {		close(ctxt->control_file_desc);		ctxt->control_file_desc = -1;		return(-1);	}	/*	* Do the authentication	*/	res = ftp_send_user(ctxt);	if (res < 0) {		close(ctxt->control_file_desc);		ctxt->control_file_desc = -1;		return(-1);	}	res = ftp_get_response(ctxt);	switch (res) {		case 2:		return(0);		case 3:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -