"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "qftp-0.98/ftpconn.cc" of archive qftp-0.98.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  *  qftp
    3  *  Copyright (C) 1997,1998 Peter Strand
    4  *  Distributed under the GNU Pulic Licence
    5  */
    6 
    7 #include <sys/stat.h>
    8 #include <unistd.h>
    9 #include <errno.h>
   10 #include <stdio.h>
   11 #include <stdlib.h>
   12 #include <string.h>
   13 #include <unistd.h>
   14 #include <fcntl.h>
   15 #include <time.h>
   16 #include <ctype.h>
   17 
   18 #include "net.h"
   19 #include "ftpconn.h"
   20 #include "misc.h"
   21 
   22 
   23 FtpConn::FtpConn()
   24 {
   25 	ctrl = new Socket;
   26 	data = NULL;
   27 	cwdch = 1;
   28 	conn = 0;
   29 }
   30 
   31 FtpConn::~FtpConn()
   32 {
   33 }
   34 
   35 int FtpConn::Connect(char *host)
   36 {
   37 	Host h(host);
   38 	if (!ctrl)
   39 		ctrl = new Socket;
   40 	cwdch = 1;
   41 	if (ctrl->Connect(h))
   42 		return -1;
   43 	if (!GetReply())
   44 		return 1;
   45 	conn = 1;
   46 	return 0;
   47 }
   48 
   49 void FtpConn::Close()
   50 {
   51 	if (conn) {
   52 		Cmd("QUIT");
   53 		GetReply();
   54 	}
   55 	conn = 0;
   56 	if (ctrl) {
   57 		ctrl->Close();
   58 		ctrl = NULL;
   59 	}
   60 	if (data) {
   61 		data->Close();
   62 		data = NULL;
   63 	}
   64 }
   65 
   66 int FtpConn::Cmd(char *cm, char *arg = NULL)
   67 {
   68 	char buf[1024];
   69 
   70 	if (arg && *arg)
   71 		sprintf(buf, "%s %s", cm, arg);
   72 	else
   73 		sprintf(buf, "%s", cm);
   74 	if (ctrl->Writeln(buf))
   75 		return -1;
   76 	return GetReply();
   77 }
   78 
   79 int FtpConn::GetReply()
   80 {
   81 	int i;
   82 
   83 	if (ctrl->Readln(retmsg) == -1)
   84 		return -1;
   85 	retval = atoi(retmsg);
   86 	i = 0;
   87 	if (retmsg[3] == '-') {
   88 		do {
   89 			i += strlen(&retmsg[i]);
   90 			if (ctrl->Readln(&retmsg[i]) == -1)
   91 				return -1;
   92 		} while ((atoi(&retmsg[i]) == retval)?(retmsg[i + 3] == '-'):1);
   93 	}
   94 	i += strlen(retmsg);
   95 	return retval;
   96 }
   97 
   98 int FtpConn::Get(char *s, int fd, void (*cbf)(int,char *t=NULL) = NULL)
   99 {
  100 	Socket *ns;
  101 	char buf[4096];
  102 	int n;
  103 
  104 	data = new Socket(ctrl);
  105 	if (data->Listen() == -1)
  106 		return -1;
  107 	if ((unsigned)Port() >= 400)
  108 		return -1;
  109 
  110 	if ((unsigned)Cmd("RETR", s) >= 400)
  111 		return -1;
  112 
  113 	if (!(ns = data->Accept()))
  114 		return -1;
  115 	if (cbf)
  116 		cbf(-1, s);
  117 	while ((n = ns->Read(buf, 4096))) {
  118 		write(fd, buf, n);
  119 		if (cbf)
  120 			cbf(n);
  121 	}
  122 	delete ns;
  123 	delete data;
  124 	return (GetReply() == -1)?-1:0;
  125 }
  126 
  127 
  128 int FtpConn::Put(char *s, int fd, void (*cbf)(int,char *t=NULL) = NULL)
  129 {
  130 	Socket *ns;
  131 	char buf[4096];
  132 	int n;
  133 
  134 	data = new Socket(ctrl);
  135 	if (data->Listen() == -1)
  136 		return -1;
  137 	if ((unsigned)Port() >= 400)
  138 		return -1;
  139 
  140 	if ((unsigned)Cmd("STOR", s) >= 400)
  141 		return -1;
  142 
  143 	if (!(ns = data->Accept()))
  144 		return -1;
  145 	if (cbf)
  146 		cbf(-1,s);
  147 	while ((n = read(fd, buf, 4096)) > 0) {
  148 		ns->Write(buf, n);
  149 		if (cbf)
  150 			cbf(n);
  151 	}
  152 	delete ns;
  153 	delete data;
  154 	return (GetReply() == -1)?-1:0;
  155 }
  156 
  157 
  158 int FtpConn::Quote(char *s)
  159 {
  160 	return Cmd(s, NULL);
  161 }
  162 
  163 int FtpConn::Cd(char *s = NULL)
  164 {
  165 	cwdch = 1;
  166 	return Cmd("CWD", s);
  167 }
  168 
  169 int FtpConn::Size(char *s)
  170 {
  171 	return Cmd("SIZE", s);
  172 }
  173 
  174 int FtpConn::MTime(char *s, time_t &t)
  175 {
  176 	struct tm tmb;
  177 
  178 	if (Cmd("MDTM", s) > 300)
  179 		return -1;
  180 
  181 	tmb.tm_year = (retmsg[6] - 0x30) * 10 + retmsg[7] - 0x30;
  182 	tmb.tm_mon = (retmsg[8] - 0x30) * 10 + retmsg[9] - 0x31;
  183 	tmb.tm_mday = (retmsg[10] - 0x30) * 10 + retmsg[11] - 0x30;
  184 	tmb.tm_hour = (retmsg[12] - 0x30) * 10 + retmsg[13] - 0x31;
  185 	tmb.tm_min = (retmsg[14] - 0x30) * 10 + retmsg[15] - 0x30;
  186 	tmb.tm_sec = (retmsg[16] - 0x30) * 10 + retmsg[17] - 0x30;
  187 	t = mktime(&tmb);
  188 	return 0;
  189 }
  190 
  191 int FtpConn::Login(char *user, char *pass)
  192 {
  193 	if ((unsigned)Cmd("USER", user) >= 400)
  194 		return -1;
  195 	if ((unsigned)Cmd("PASS", (*pass)?pass:"") >= 400)
  196 		return -1;
  197 	return 0;
  198 }
  199 
  200 DirList *FtpConn::clookup(char *s)
  201 {
  202 	int i, n;
  203 
  204 	n = cache.size();
  205 	for (i = 0;i < n;i++)
  206 		if (!strcmp(cache[i]->path, s))
  207 			return cache[i];
  208 	return NULL;
  209 }
  210 
  211 void FtpConn::cset(char *s, DirList *dl)
  212 {
  213 	int i, n;
  214 
  215 	n = cache.size();
  216 	for (i = 0;i < n;i++)
  217 		if (!strcmp(cache[i]->path, s))
  218 			break;
  219 	if (n == i) {
  220 		dl->path = strdup(s);
  221 		cache.push_back(dl);
  222 	} else {
  223 		free(cache[i]->path);
  224 		cache[i] = dl;
  225 		cache[i]->path = strdup(s);
  226 	}
  227 }
  228 
  229 int FtpConn::List(DirList &dl, char *s)
  230 {
  231 	Entry e;
  232 	int i;
  233 	char *p, path[256];
  234 
  235 	DirList *t;
  236 
  237 	p = split(GetCwd(), s, path);
  238 
  239 	if (!(t = clookup(path))) {
  240 		t = new DirList;
  241 		list(t, path);
  242 		cset(path, t);
  243 	}
  244 	t->Reset();
  245 	i = 0;
  246 	while (!i && t->GetNext(e))
  247 		if (!strcmp(e.name, p))
  248 			i++;
  249 	if (i && e.type == 'd') {
  250 		strcat(path, "/");
  251 		strcat(path, p);
  252 		if (!(t = clookup(path))) {
  253 			t = new DirList;
  254 			list(t, path);
  255 			cset(path, t);
  256 		}
  257 		p = "";
  258 	}
  259 	t = clookup(path);
  260 	dl = *t;
  261 	return 0;
  262 }
  263 
  264 
  265 int FtpConn::list(DirList *dl, char *path)
  266 {
  267 	Socket *ns;
  268 	char buf[500];
  269 	int i;
  270 	Entry e;
  271 	data = new Socket(ctrl);
  272 	if (data->Listen() == -1)
  273 		return -1;
  274 	if ((unsigned)Port() >= 400)
  275 		return -1;
  276 	if ((unsigned)Cmd("NLST -Fa", path) >= 400)
  277 		return -1;
  278 	if (!(ns = data->Accept()))
  279 		return -1;
  280 	dl->Flush();
  281 	dl->isused = 1;
  282 	if (!ns->Readln(buf))
  283 		return -1;
  284 	if (!ns->Readln(buf))
  285 		return -1;
  286 	while ((i = ns->Readln(buf))) {
  287 		if (i == -1)
  288 			return -1;
  289 		i = strlen(buf) - 1;
  290 		if (buf[i] == '\n' || buf[i] == '\r') {
  291 			buf[i] = 0;
  292 			i--;
  293 		}
  294 		if (buf[i] == '\n' || buf[i] == '\r') {
  295 			buf[i] = 0;
  296 			i--;
  297 		}
  298 		e.type = '-';
  299 		if (buf[i] == '/' || buf[i] == '*' || buf[i] == '@') {
  300 			if (buf[i] == '/')
  301 				e.type = 'd';
  302 			else if (buf[i] == '@')
  303 				e.type = 'l';
  304 			buf[i] = 0;
  305 		}
  306 		e.name = strdup(buf);
  307 		e.perm = -1;
  308 		e.date = NULL;
  309 		e.user = NULL;
  310 		e.group = NULL;
  311 		e.size = -1;
  312 		dl->Add(e);
  313 	}
  314 	GetReply();
  315 	delete ns;
  316 	delete data;
  317 	data = NULL;
  318 	return 0;
  319 }
  320 
  321 int FtpConn::LongList(DirList &dl, char *s = NULL)
  322 {
  323 	Entry e;
  324 	int i;
  325 	char *p, path[256];
  326 
  327 	DirList *t;
  328 
  329 	p = split(GetCwd(), s, path);
  330 
  331 	if (!(t = clookup(path)) || !t->islong) {
  332 		t = new DirList;
  333 		longList(t, path);
  334 		cset(path, t);
  335 	}
  336 	t->Reset();
  337 	i = 0;
  338 	while (!i && t->GetNext(e))
  339 		if (!strcmp(e.name, p))
  340 			i++;
  341 	if (i && e.type == 'd') {
  342 		strcat(path, "/");
  343 		strcat(path, p);
  344 		if (!(t = clookup(path)) || !t->islong) {
  345 			t = new DirList;
  346 			longList(t, path);
  347 			cset(path, t);
  348 		}
  349 		p = "";
  350 	}
  351 	t = clookup(path);
  352 	dl = *t;
  353 	return 0;
  354 }
  355 
  356 int FtpConn::longList(DirList *dl, char *s = NULL)
  357 {
  358 	Socket *ns;
  359 	char buf[500], *p1, *p2;
  360 	Entry e;
  361 	int i;
  362 
  363 	data = new Socket(ctrl);
  364 	if (data->Listen() == -1)
  365 		return -1;
  366 	if ((unsigned)Port() >= 400)
  367 		return -1;
  368 	if ((unsigned)Cmd("LIST -a", s) >= 400)
  369 		return -1;
  370 	if (!(ns = data->Accept()))
  371 		return -1;
  372 	if (!ns->Readln(buf))
  373 		return -1;
  374 	if (!ns->Readln(buf))
  375 		return -1;
  376 	if (!ns->Readln(buf))
  377 		return -1;
  378 	dl->Flush();
  379 	while ((i = ns->Readln(buf))) {
  380 		if (i == -1)
  381 			return -1;
  382 		i = strlen(buf) - 1;
  383 		if (buf[i] == '\n' || buf[i] == '\r') {
  384 			buf[i] = 0;
  385 			i--;
  386 		}
  387 		if (buf[i] == '\n' || buf[i] == '\r') {
  388 			buf[i] = 0;
  389 			i--;
  390 		}
  391 		e.type = buf[0];
  392 		e.perm = 0;
  393 		if (buf[1] == 'r')
  394 			e.perm |= 0400;
  395 		if (buf[2] == 'w')
  396 			e.perm |= 0200;
  397 		if (buf[3] == 'x')
  398 			e.perm |= 0100;
  399 		if (buf[4] == 'r')
  400 			e.perm |= 0040;
  401 		if (buf[5] == 'w')
  402 			e.perm |= 0020;
  403 		if (buf[6] == 'x')
  404 			e.perm |= 0010;
  405 		if (buf[7] == 'r')
  406 			e.perm |= 0004;
  407 		if (buf[8] == 'w')
  408 			e.perm |= 0002;
  409 		if (buf[9] == 'x')
  410 			e.perm |= 0001;
  411 		if (buf[3] == 's')
  412 			e.perm |= 04000;
  413 		if (buf[6] == 's')
  414 			e.perm |= 02000;
  415 		if (buf[9] == 's')
  416 			e.perm |= 01000;
  417 		p1 = &buf[10];
  418 
  419 		while (isspace(*p1)) p1++; while (!isspace(*p1)) p1++;
  420 		buf[10] = 0;
  421 		e.perms = strdup(buf);
  422 		while (isspace(*p1)) p1++; p2 = p1; while (!isspace(*p2)) p2++; *p2 = 0;
  423 		e.user = strdup(p1);
  424 		p1 = p2 + 1;
  425 
  426 		while (isspace(*p1)) p1++; p2 = p1; while (!isspace(*p2)) p2++; *p2 = 0;
  427 		e.group = strdup(p1);
  428 		p1 = p2 + 1;
  429 
  430 		while (isspace(*p1)) p1++; p2 = p1; while (!isspace(*p2)) p2++; *p2 = 0;
  431 		e.size = atol(p1);
  432 		p1 = p2 + 1;
  433 
  434 		while (isspace(*p1)) p1++;
  435 		p2 = p1;
  436 		while (!isspace(*p2)) p2++; while (isspace(*p2)) p2++;
  437 		while (!isspace(*p2)) p2++; while (isspace(*p2)) p2++;
  438 		while (!isspace(*p2)) p2++; while (isspace(*p2)) p2++;
  439 		*--p2 = 0;
  440 		e.date = strdup(p1);
  441 		p1 = p2 + 1;
  442 		while (isspace(*p1))
  443 			p1++;
  444 		p2 = p1;
  445 		while (*p2 && !isspace(*p2))
  446 			p2++;
  447 		*p2 = 0;
  448 		e.name = strdup(p1);
  449 		dl->Add(e);
  450 	}
  451 	dl->islong = 1;
  452 	delete ns;
  453 	delete data;
  454 	data = NULL;
  455 	return (GetReply() == -1)?-1:0;
  456 }
  457 
  458 
  459 char *FtpConn::GetHost()
  460 {
  461 	return ctrl->GetRHost();
  462 }
  463 
  464 char *FtpConn::GetMsg()
  465 {
  466 	return retmsg;
  467 }
  468 
  469 const char *FtpConn::GetError()
  470 {
  471 	return ctrl->GetError();
  472 }
  473 
  474 char *FtpConn::GetCwd()
  475 {
  476 	char *p;
  477 	int i;
  478 	if (cwdch) {
  479 		if ((unsigned)Cmd("PWD") >= 400)
  480 			return "";
  481 		p = strchr(retmsg, '"') + 1;
  482 		i = 0;
  483 		while ((cwd[i++] = *p++) != '"');
  484 		cwd[i - 1] = 0;
  485 	}
  486 	cwdch = 0;
  487 	return cwd;
  488 }
  489 
  490 int FtpConn::Port()
  491 {
  492 	char buf[500];
  493 	long badr, bp;
  494 	badr = ntohl(data->GetLAddr());
  495 	bp = ntohs(data->GetLPort());
  496 	sprintf(buf, "%d,%d,%d,%d,%d,%d", (int) (badr >> 24) & 0xff,
  497 		(int) (badr >> 16) & 0xff, (int) (badr >> 8) & 0xff,
  498 		(int) badr & 0xff, (int) (bp >> 8) & 0xff, (int) bp & 0xff);
  499 	return Cmd("PORT", buf);
  500 }
  501