00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include <time.h>
00025
#include "ftpparse.h"
00026
00027 static long totai(
long year,
long month,
long mday)
00028 {
00029
long result;
00030
if (month >= 2) month -= 2;
00031
else { month += 10; --year; }
00032 result = (mday - 1) * 10 + 5 + 306 * month;
00033 result /= 10;
00034
if (result == 365) { year -= 3; result = 1460; }
00035
else result += 365 * (year % 4);
00036 year /= 4;
00037 result += 1461 * (year % 25);
00038 year /= 25;
00039
if (result == 36524) { year -= 3; result = 146096; }
00040
else { result += 36524 * (year % 4); }
00041 year /= 4;
00042 result += 146097 * (year - 5);
00043 result += 11017;
00044
return result * 86400;
00045 }
00046
00047 static int flagneedbase = 1;
00048 static time_t
base;
00049 static long now;
00050 static int flagneedcurrentyear = 1;
00051 static long currentyear;
00052
00053 static void initbase(
void)
00054 {
00055
struct tm *t;
00056
if (!
flagneedbase)
return;
00057
00058
base = 0;
00059 t = gmtime(&
base);
00060
base = -(
totai(t->tm_year + 1900,t->tm_mon,t->tm_mday) + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);
00061
00062
00063
flagneedbase = 0;
00064 }
00065
00066 static void initnow(
void)
00067 {
00068
long day;
00069
long year;
00070
00071
initbase();
00072
now = time((time_t *) 0) -
base;
00073
00074
if (
flagneedcurrentyear) {
00075 day =
now / 86400;
00076
if ((
now % 86400) < 0) --day;
00077 day -= 11017;
00078 year = 5 + day / 146097;
00079 day = day % 146097;
00080
if (day < 0) { day += 146097; --year; }
00081 year *= 4;
00082
if (day == 146096) { year += 3; day = 36524; }
00083
else { year += day / 36524; day %= 36524; }
00084 year *= 25;
00085 year += day / 1461;
00086 day %= 1461;
00087 year *= 4;
00088
if (day == 1460) { year += 3; day = 365; }
00089
else { year += day / 365; day %= 365; }
00090 day *= 10;
00091
if ((day + 5) / 306 >= 10) ++year;
00092
currentyear = year;
00093
flagneedcurrentyear = 0;
00094 }
00095 }
00096
00097
00098
00099
00100
00101 static long guesstai(
long month,
long mday)
00102 {
00103
long year;
00104
long t;
00105
00106
initnow();
00107
00108
for (year =
currentyear - 1;year <
currentyear + 100;++year) {
00109 t =
totai(year,month,mday);
00110
if (
now - t < 350 * 86400)
00111
return t;
00112 }
00113
return 0;
00114 }
00115
00116 static int check(
char *buf,
char *monthname)
00117 {
00118
if ((buf[0] != monthname[0]) && (buf[0] != monthname[0] - 32))
return 0;
00119
if ((buf[1] != monthname[1]) && (buf[1] != monthname[1] - 32))
return 0;
00120
if ((buf[2] != monthname[2]) && (buf[2] != monthname[2] - 32))
return 0;
00121
return 1;
00122 }
00123
00124 static char *
months[12] = {
00125
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec"
00126 } ;
00127
00128 static int getmonth(
char *buf,
int len)
00129 {
00130
int i;
00131
if (len == 3)
00132
for (i = 0;i < 12;++i)
00133
if (
check(buf,
months[i]))
return i;
00134
return -1;
00135 }
00136
00137 static long getlong(
char *buf,
int len)
00138 {
00139
long u = 0;
00140
while (len-- > 0)
00141 u = u * 10 + (*buf++ -
'0');
00142
return u;
00143 }
00144
00145 int ftpparse(
struct ftpparse *fp,
char *buf,
int len)
00146 {
00147
int i;
00148
int j;
00149
int state;
00150
long size = 0;
00151
long year;
00152
long month = 0;
00153
long mday = 0;
00154
long hour;
00155
long minute;
00156
00157 fp->
name = 0;
00158 fp->
namelen = 0;
00159 fp->
flagtrycwd = 0;
00160 fp->
flagtryretr = 0;
00161 fp->
sizetype =
FTPPARSE_SIZE_UNKNOWN;
00162 fp->
size = 0;
00163 fp->
mtimetype =
FTPPARSE_MTIME_UNKNOWN;
00164 fp->
mtime = 0;
00165 fp->
idtype =
FTPPARSE_ID_UNKNOWN;
00166 fp->
id = 0;
00167 fp->
idlen = 0;
00168
00169
if (len < 2)
00170
return 0;
00171
00172
switch(*buf) {
00173
00174
00175
00176
case '+':
00177 i = 1;
00178
for (j = 1;j < len;++j) {
00179
if (buf[j] == 9) {
00180 fp->
name = buf + j + 1;
00181 fp->
namelen = len - j - 1;
00182
return 1;
00183 }
00184
if (buf[j] ==
',') {
00185
switch(buf[i]) {
00186
case '/':
00187 fp->
flagtrycwd = 1;
00188
break;
00189
case 'r':
00190 fp->
flagtryretr = 1;
00191
break;
00192
case 's':
00193 fp->
sizetype =
FTPPARSE_SIZE_BINARY;
00194 fp->
size =
getlong(buf + i + 1,j - i - 1);
00195
break;
00196
case 'm':
00197 fp->
mtimetype =
FTPPARSE_MTIME_LOCAL;
00198
initbase();
00199 fp->
mtime =
base +
getlong(buf + i + 1,j - i - 1);
00200
break;
00201
case 'i':
00202 fp->
idtype =
FTPPARSE_ID_FULL;
00203 fp->
id = buf + i + 1;
00204 fp->
idlen = j - i - 1;
00205 }
00206 i = j + 1;
00207 }
00208 }
00209
return 0;
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
case 'b':
00228
case 'c':
00229
case 'd':
00230
case 'l':
00231
case 'p':
00232
case 's':
00233
case '-':
00234
00235
if (*buf ==
'd') fp->
flagtrycwd = 1;
00236
if (*buf ==
'-') fp->
flagtryretr = 1;
00237
if (*buf ==
'l') fp->
flagtrycwd = fp->
flagtryretr = 1;
00238
00239 state = 1;
00240 i = 0;
00241
for (j = 1;j < len;++j)
00242
if ((buf[j] ==
' ') && (buf[j - 1] !=
' ')) {
00243
switch(state) {
00244
case 1:
00245 state = 2;
00246
break;
00247
case 2:
00248 state = 3;
00249
if ((j - i == 6) && (buf[i] ==
'f'))
00250 state = 4;
00251
break;
00252
case 3:
00253 state = 4;
00254
break;
00255
case 4:
00256 size =
getlong(buf + i,j - i);
00257 state = 5;
00258
break;
00259
case 5:
00260 month =
getmonth(buf + i,j - i);
00261
if (month >= 0)
00262 state = 6;
00263
else
00264 size =
getlong(buf + i,j - i);
00265
break;
00266
case 6:
00267 mday =
getlong(buf + i,j - i);
00268 state = 7;
00269
break;
00270
case 7:
00271
if ((j - i == 4) && (buf[i + 1] ==
':')) {
00272 hour =
getlong(buf + i,1);
00273 minute =
getlong(buf + i + 2,2);
00274 fp->
mtimetype =
FTPPARSE_MTIME_REMOTEMINUTE;
00275
initbase();
00276 fp->
mtime =
base +
guesstai(month,mday) + hour * 3600 + minute * 60;
00277 }
else if ((j - i == 5) && (buf[i + 2] ==
':')) {
00278 hour =
getlong(buf + i,2);
00279 minute =
getlong(buf + i + 3,2);
00280 fp->
mtimetype =
FTPPARSE_MTIME_REMOTEMINUTE;
00281
initbase();
00282 fp->
mtime =
base +
guesstai(month,mday) + hour * 3600 + minute * 60;
00283 }
00284
else if (j - i >= 4) {
00285 year =
getlong(buf + i,j - i);
00286 fp->
mtimetype =
FTPPARSE_MTIME_REMOTEDAY;
00287
initbase();
00288 fp->
mtime =
base +
totai(year,month,mday);
00289 }
00290
else
00291
return 0;
00292 fp->
name = buf + j + 1;
00293 fp->
namelen = len - j - 1;
00294 state = 8;
00295
break;
00296
case 8:
00297
break;
00298 }
00299 i = j + 1;
00300
while ((i < len) && (buf[i] ==
' ')) ++i;
00301 }
00302
00303
if (state != 8)
00304
return 0;
00305
00306 fp->
size = size;
00307 fp->
sizetype =
FTPPARSE_SIZE_BINARY;
00308
00309
if (*buf ==
'l')
00310
for (i = 0;i + 3 < fp->
namelen;++i)
00311
if (fp->
name[i] ==
' ')
00312
if (fp->
name[i + 1] ==
'-')
00313
if (fp->
name[i + 2] ==
'>')
00314
if (fp->
name[i + 3] ==
' ') {
00315 fp->
namelen = i;
00316
break;
00317 }
00318
00319
00320
if ((buf[1] ==
' ') || (buf[1] ==
'['))
00321
if (fp->
namelen > 3)
00322
if (fp->
name[0] ==
' ')
00323
if (fp->
name[1] ==
' ')
00324
if (fp->
name[2] ==
' ') {
00325 fp->
name += 3;
00326 fp->
namelen -= 3;
00327 }
00328
00329
return 1;
00330 }
00331
00332
00333
00334
00335
00336
00337
for (i = 0;i < len;++i)
00338
if (buf[i] ==
';')
00339
break;
00340
if (i < len) {
00341 fp->
name = buf;
00342 fp->
namelen = i;
00343
if (i > 4)
00344
if (buf[i - 4] ==
'.')
00345
if (buf[i - 3] ==
'D')
00346
if (buf[i - 2] ==
'I')
00347
if (buf[i - 1] ==
'R') {
00348 fp->
namelen -= 4;
00349 fp->
flagtrycwd = 1;
00350 }
00351
if (!fp->
flagtrycwd)
00352 fp->
flagtryretr = 1;
00353
while (buf[i] !=
' ')
if (++i == len)
return 0;
00354
while (buf[i] ==
' ')
if (++i == len)
return 0;
00355
while (buf[i] !=
' ')
if (++i == len)
return 0;
00356
while (buf[i] ==
' ')
if (++i == len)
return 0;
00357 j = i;
00358
while (buf[j] !=
'-')
if (++j == len)
return 0;
00359 mday =
getlong(buf + i,j - i);
00360
while (buf[j] ==
'-')
if (++j == len)
return 0;
00361 i = j;
00362
while (buf[j] !=
'-')
if (++j == len)
return 0;
00363 month =
getmonth(buf + i,j - i);
00364
if (month < 0)
return 0;
00365
while (buf[j] ==
'-')
if (++j == len)
return 0;
00366 i = j;
00367
while (buf[j] !=
' ')
if (++j == len)
return 0;
00368 year =
getlong(buf + i,j - i);
00369
while (buf[j] ==
' ')
if (++j == len)
return 0;
00370 i = j;
00371
while (buf[j] !=
':')
if (++j == len)
return 0;
00372 hour =
getlong(buf + i,j - i);
00373
while (buf[j] ==
':')
if (++j == len)
return 0;
00374 i = j;
00375
while ((buf[j] !=
':') && (buf[j] !=
' '))
if (++j == len)
return 0;
00376 minute =
getlong(buf + i,j - i);
00377
00378 fp->
mtimetype =
FTPPARSE_MTIME_REMOTEMINUTE;
00379
initbase();
00380 fp->
mtime =
base +
totai(year,month,mday) + hour * 3600 + minute * 60;
00381
00382
return 1;
00383 }
00384
00385
00386
00387
00388
00389
if ((*buf >=
'0') && (*buf <=
'9')) {
00390 i = 0;
00391 j = 0;
00392
while (buf[j] !=
'-')
if (++j == len)
return 0;
00393 month =
getlong(buf + i,j - i) - 1;
00394
while (buf[j] ==
'-')
if (++j == len)
return 0;
00395 i = j;
00396
while (buf[j] !=
'-')
if (++j == len)
return 0;
00397 mday =
getlong(buf + i,j - i);
00398
while (buf[j] ==
'-')
if (++j == len)
return 0;
00399 i = j;
00400
while (buf[j] !=
' ')
if (++j == len)
return 0;
00401 year =
getlong(buf + i,j - i);
00402
if (year < 50) year += 2000;
00403
if (year < 1000) year += 1900;
00404
while (buf[j] ==
' ')
if (++j == len)
return 0;
00405 i = j;
00406
while (buf[j] !=
':')
if (++j == len)
return 0;
00407 hour =
getlong(buf + i,j - i);
00408
while (buf[j] ==
':')
if (++j == len)
return 0;
00409 i = j;
00410
while ((buf[j] !=
'A') && (buf[j] !=
'P'))
if (++j == len)
return 0;
00411 minute =
getlong(buf + i,j - i);
00412
if (hour == 12) hour = 0;
00413
if (buf[j] ==
'A')
if (++j == len)
return 0;
00414
if (buf[j] ==
'P') { hour += 12;
if (++j == len)
return 0; }
00415
if (buf[j] ==
'M')
if (++j == len)
return 0;
00416
00417
while (buf[j] ==
' ')
if (++j == len)
return 0;
00418
if (buf[j] ==
'<') {
00419 fp->
flagtrycwd = 1;
00420
while (buf[j] !=
' ')
if (++j == len)
return 0;
00421 }
00422
else {
00423 i = j;
00424
while (buf[j] !=
' ')
if (++j == len)
return 0;
00425 fp->
size =
getlong(buf + i,j - i);
00426 fp->
sizetype =
FTPPARSE_SIZE_BINARY;
00427 fp->
flagtryretr = 1;
00428 }
00429
while (buf[j] ==
' ')
if (++j == len)
return 0;
00430
00431 fp->
name = buf + j;
00432 fp->
namelen = len - j;
00433
00434 fp->
mtimetype =
FTPPARSE_MTIME_REMOTEMINUTE;
00435
initbase();
00436 fp->
mtime =
base +
totai(year,month,mday) + hour * 3600 + minute * 60;
00437
00438
return 1;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
return 0;
00448 }