src/lib/net.c 1.68
1.68 2009/02/18 00:33:25 galt
Adding FTP support for udc cache lib
Index: src/lib/net.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/net.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -b -B -U 4 -r1.67 -r1.68
--- src/lib/net.c 12 Feb 2009 01:18:00 -0000 1.67
+++ src/lib/net.c 18 Feb 2009 00:33:25 -0000 1.68
@@ -474,9 +474,8 @@
int parsePasvPort(char *rs)
/* parse PASV reply to get the port and return it */
{
-char *rsCopy = strdup(rs);
char *words[7];
int wordCount;
char *rsStart = strchr(rs,'(');
char *rsEnd = strchr(rs,')');
@@ -486,13 +485,183 @@
wordCount = chopString(rsStart, ",", words, ArraySize(words));
if (wordCount != 6)
errAbort("PASV reply does not parse correctly");
result = atoi(words[4])*256+atoi(words[5]);
-freez(&rsCopy);
return result;
}
+long long parseFtpSIZE(char *rs)
+/* parse reply to SIZE and return it */
+{
+char *words[3];
+int wordCount;
+char *rsStart = rs;
+long long result = 0;
+wordCount = chopString(rsStart, " ", words, ArraySize(words));
+if (wordCount != 2)
+ errAbort("SIZE reply does not parse correctly");
+result = atoll(words[1]);
+return result;
+}
+
+
+time_t parseFtpMDTM(char *rs)
+/* parse reply to MDTM and return it
+ * 200 YYYYMMDDhhmmss */
+{
+char spread[] = "YYYY MM DD hh mm ss";
+char *to = spread;
+char *from = NULL;
+char *words[3];
+int wordCount;
+char *rsStart = rs;
+int len = strlen(rs);
+if (len == 0)
+ return FALSE;
+char *rsLast = rs + len - 1;
+if (*rsLast == '\n')
+ {
+ *rsLast = 0;
+ --rsLast;
+ --len;
+ if (len == 0)
+ return FALSE;
+ }
+if (*rsLast == '\r')
+ {
+ *rsLast = 0;
+ --rsLast;
+ --len;
+ if (len == 0)
+ return FALSE;
+ }
+wordCount = chopString(rsStart, " ", words, ArraySize(words));
+if (wordCount != 2)
+ errAbort("MDTM reply does not parse correctly");
+
+//printf("MDTM parse string [%s], length=%lld\n", words[1], (long long) strlen(words[1]));
+
+from = words[1];
+
+*to++ = *from++;
+*to++ = *from++;
+*to++ = *from++;
+*to++ = *from++;
+*to++ = '-';
+*to++ = *from++;
+*to++ = *from++;
+*to++ = '-';
+*to++ = *from++;
+*to++ = *from++;
+*to++ = ' ';
+*to++ = *from++;
+*to++ = *from++;
+*to++ = ':';
+*to++ = *from++;
+*to++ = *from++;
+*to++ = ':';
+*to++ = *from++;
+*to++ = *from++;
+*to++ = 0;
+
+// printf("MDTM to [%s], length=%lld\n", spread, (long long) strlen(spread));
+
+struct tm tm;
+time_t t;
+
+if (strptime(spread, "%Y-%m-%d %H:%M:%S", &tm) == NULL)
+ { /* Handle error */;
+ errAbort("unable to parse MDTM string [%s]", spread);
+ }
+
+//printf("year: %d; month: %d; day: %d;\n",
+// tm.tm_year, tm.tm_mon, tm.tm_mday);
+//printf("hour: %d; minute: %d; second: %d\n",
+// tm.tm_hour, tm.tm_min, tm.tm_sec);
+//printf("week day: %d; year day: %d\n", tm.tm_wday, tm.tm_yday);
+
+
+tm.tm_isdst = -1; /* Not set by strptime(); tells mktime()
+ to determine whether daylight saving time
+ is in effect */
+t = mktime(&tm);
+if (t == -1)
+ { /* Handle error */;
+ errAbort("mktime failed while parsing last-modified string [%s]", words[1]);
+ }
+
+//printf("seconds since the Epoch: %lld\n", (long long) t);"
+
+return t;
+}
+
+
+
+boolean netGetFtpInfo(char *url, long long *retSize, time_t *retTime)
+/* Return date and size of ftp url file */
+{
+struct netParsedUrl npu;
+struct dyString *rs = NULL;
+int sd;
+long timeOut = 1000000; /* wait in microsec */
+char cmd[256];
+
+// TODO maybe remove this workaround where udc cache wants info on URL "/" ?
+
+/* Parse the URL and connect. */
+netParseUrl(url, &npu);
+
+if (!sameString(npu.protocol, "ftp"))
+ errAbort("Sorry, can only netOpen ftp's currently");
+
+if (sameString(npu.file,"/"))
+ {
+ *retSize = 0;
+ *retTime = time(NULL);
+ return TRUE;
+ }
+
+sd = netMustConnect(npu.host, atoi(npu.port));
+
+/* Ask remote ftp server for file info. */
+
+/* don't send a command, just read the welcome msg */
+if (readReadyWait(sd, timeOut))
+ sendFtpCommand(sd, "", FALSE);
+
+safef(cmd,sizeof(cmd),"USER %s\r\n", npu.user);
+sendFtpCommand(sd, cmd, FALSE);
+
+safef(cmd,sizeof(cmd),"PASS %s\r\n", npu.password);
+sendFtpCommand(sd, cmd, FALSE);
+
+sendFtpCommand(sd, "TYPE I\r\n", FALSE); // Not sure this is required for just size/date
+/* 200 Type set to I */
+/* (send the data as binary, so can support compressed files) */
+
+safef(cmd,sizeof(cmd),"SIZE %s\r\n", npu.file);
+rs = sendFtpCommand(sd, cmd, TRUE);
+*retSize = parseFtpSIZE(rs->string);
+/* 200 12345 */
+
+/* Clean up and return handle. */
+dyStringFree(&rs);
+
+safef(cmd,sizeof(cmd),"MDTM %s\r\n", npu.file);
+rs = sendFtpCommand(sd, cmd, TRUE);
+*retTime = parseFtpMDTM(rs->string);
+/* 200 YYYYMMDDhhmmss */
+
+/* Clean up and return handle. */
+dyStringFree(&rs);
+
+close(sd);
+
+return TRUE;
+}
+
+
int netGetOpenFtp(char *url)
/* Return a file handle that will read the url. */
{
struct netParsedUrl npu;