1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ftpdirp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
39 #include "ftpdirp.hxx"
47 typedef sal_uInt32 ULONG
;
50 inline sal_Bool
ascii_isLetter( sal_Unicode ch
)
52 return (( (ch
>= 0x0041) && (ch
<= 0x005A)) ||
53 (( ch
>= 0x0061) && (ch
<= 0x007A)));
56 inline sal_Bool
ascii_isWhitespace( sal_Unicode ch
)
58 return ((ch
<= 0x20) && ch
);
63 /*========================================================================
65 * FTPDirectoryParser implementation.
67 *======================================================================*/
70 * Accepts one of two styles:
72 * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP
73 * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP
74 * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET
76 * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name
78 * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT
79 * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET
81 * interpreted as: size attribs DIR mm-dd-yy hh:mm name
84 sal_Bool
FTPDirectoryParser::parseDOS (
86 const sal_Char
*pBuffer
)
88 sal_Bool bDirectory
= false;
91 sal_uInt16 nMonth
= 0;
94 sal_uInt16 nMinute
= 0;
100 STATE_1_DAY
, STATE_1_YEAR
, STATE_1_YEAR_LWS
, STATE_1_HOUR
,
101 STATE_1_MINUTE
, STATE_1_MINUTE_LWS
, STATE_1_AP
,
102 STATE_1_APM
, STATE_1_LESS
, STATE_1_D
, STATE_1_DI
,
103 STATE_1_DIR
, STATE_1_SIZE
,
104 STATE_2_SIZE
, STATE_2_SIZE_LWS
, STATE_2_ATTRIB
,
105 STATE_2_D
, STATE_2_DI
, STATE_2_DIR_LWS
,
106 STATE_2_MONTH
, STATE_2_DAY
, STATE_2_YEAR
, STATE_2_YEAR_LWS
,
107 STATE_2_HOUR
, STATE_2_MINUTE
,
113 enum StateType eState
= STATE_INIT_LWS
;
114 for (const sal_Char
*p
= pBuffer
;
115 eState
!= STATE_ERROR
&& *p
;
121 if (*p
>= '0' && *p
<= '9')
125 eState
= STATE_MONTH_OR_SIZE
;
127 else if (!ascii_isWhitespace(*p
))
128 eState
= STATE_ERROR
;
131 case STATE_MONTH_OR_SIZE
:
132 if (*p
>= '0' && *p
<= '9')
134 nMonth
= 10 * nMonth
+ (*p
- '0');
141 eState
= STATE_2_SIZE
;
144 else if (ascii_isWhitespace(*p
))
148 eState
= STATE_2_SIZE_LWS
;
150 else if ((*p
== '.' || *p
== '-') && nMonth
&& nMonth
<= 12)
153 eState
= STATE_1_DAY
;
156 eState
= STATE_ERROR
;
160 if (*p
>= '0' && *p
<= '9')
163 nDay
= 10 * nDay
+ (*p
- '0');
167 eState
= STATE_ERROR
;
168 else if ((*p
== '.' || *p
== '-') && nDay
&& nDay
<= 31)
171 eState
= STATE_1_YEAR
;
174 eState
= STATE_ERROR
;
178 if (*p
>= '0' && *p
<= '9')
182 nYear
= 10 * nYear
+ (*p
- '0');
186 eState
= STATE_ERROR
;
190 if (ascii_isWhitespace(*p
))
191 eState
= STATE_1_YEAR_LWS
;
193 eState
= STATE_ERROR
;
197 case STATE_1_YEAR_LWS
:
198 if (*p
>= '0' && *p
<= '9')
202 eState
= STATE_1_HOUR
;
204 else if (!ascii_isWhitespace(*p
))
205 eState
= STATE_ERROR
;
209 if (*p
>= '0' && *p
<= '9')
212 nHour
= 10 * nHour
+ (*p
- '0');
216 eState
= STATE_ERROR
;
217 else if (*p
== ':' && nHour
< 24)
220 eState
= STATE_1_MINUTE
;
223 eState
= STATE_ERROR
;
227 if (*p
>= '0' && *p
<= '9')
230 nMinute
= 10 * nMinute
+ (*p
- '0');
234 eState
= STATE_ERROR
;
235 else if ((*p
== 'a' || *p
== 'A') && nMinute
< 60)
236 if (nHour
>= 1 && nHour
<= 11)
238 else if (nHour
== 12)
244 eState
= STATE_ERROR
;
245 else if ((*p
== 'p' || *p
== 'P') && nMinute
< 60)
246 if (nHour
>= 1 && nHour
<= 11)
251 else if (nHour
== 12)
254 eState
= STATE_ERROR
;
255 else if (ascii_isWhitespace(*p
) && (nMinute
< 60))
256 eState
= STATE_1_MINUTE_LWS
;
258 eState
= STATE_ERROR
;
261 case STATE_1_MINUTE_LWS
:
262 if (*p
== 'a' || *p
== 'A')
263 if (nHour
>= 1 && nHour
<= 11)
265 else if (nHour
== 12)
271 eState
= STATE_ERROR
;
272 else if (*p
== 'p' || *p
== 'P')
273 if (nHour
>= 1 && nHour
<= 11)
278 else if (nHour
== 12)
281 eState
= STATE_ERROR
;
283 eState
= STATE_1_LESS
;
284 else if (*p
>= '0' && *p
<= '9')
287 eState
= STATE_1_SIZE
;
289 else if (!ascii_isWhitespace(*p
))
290 eState
= STATE_ERROR
;
294 eState
= *p
== 'm' || *p
== 'M' ? STATE_1_APM
: STATE_ERROR
;
299 eState
= STATE_1_LESS
;
300 else if (*p
>= '0' && *p
<= '9')
303 eState
= STATE_1_SIZE
;
305 else if (!ascii_isWhitespace(*p
))
306 eState
= STATE_ERROR
;
310 eState
= *p
== 'd' || *p
== 'D' ? STATE_1_D
: STATE_ERROR
;
314 eState
= *p
== 'i' || *p
== 'I' ? STATE_1_DI
: STATE_ERROR
;
318 eState
= *p
== 'r' || *p
== 'R' ? STATE_1_DIR
: STATE_ERROR
;
325 eState
= STATE_LWS_NAME
;
328 eState
= STATE_ERROR
;
332 if (*p
>= '0' && *p
<= '9')
333 nSize
= 10 * nSize
+ (*p
- '0');
334 else if (ascii_isWhitespace(*p
))
335 eState
= STATE_LWS_NAME
;
337 eState
= STATE_ERROR
;
341 if (*p
>= '0' && *p
<= '9')
342 nSize
= 10 * nSize
+ (*p
- '0');
343 else if (ascii_isWhitespace(*p
))
344 eState
= STATE_2_SIZE_LWS
;
346 eState
= STATE_ERROR
;
349 case STATE_2_SIZE_LWS
:
350 if (*p
== 'd' || *p
== 'D')
352 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
353 eState
= STATE_2_ATTRIB
;
354 else if (*p
>= '0' && *p
<= '9')
358 eState
= STATE_2_MONTH
;
360 else if (!ascii_isWhitespace(*p
))
361 eState
= STATE_ERROR
;
365 if (ascii_isWhitespace(*p
))
366 eState
= STATE_2_SIZE_LWS
;
367 else if ((*p
< 'a' || *p
> 'z') && (*p
< 'A' || *p
> 'Z'))
368 eState
= STATE_ERROR
;
372 if (*p
== 'i' || *p
== 'I')
374 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
375 eState
= STATE_2_ATTRIB
;
376 else if (ascii_isWhitespace(*p
))
377 eState
= STATE_2_SIZE_LWS
;
379 eState
= STATE_ERROR
;
383 if (*p
== 'r' || *p
== 'R')
386 eState
= STATE_2_DIR_LWS
;
390 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
391 eState
= STATE_2_ATTRIB
;
392 else if (ascii_isWhitespace(*p
))
393 eState
= STATE_2_SIZE_LWS
;
395 eState
= STATE_ERROR
;
399 case STATE_2_DIR_LWS
:
400 if (*p
>= '0' && *p
<= '9')
404 eState
= STATE_2_MONTH
;
406 else if (!ascii_isWhitespace(*p
))
407 eState
= STATE_ERROR
;
411 if (*p
>= '0' && *p
<= '9')
414 nMonth
= 10 * nMonth
+ (*p
- '0');
418 eState
= STATE_ERROR
;
419 else if (*p
== '-' && nMonth
&& nMonth
<= 12)
422 eState
= STATE_2_DAY
;
425 eState
= STATE_ERROR
;
429 if (*p
>= '0' && *p
<= '9')
432 nDay
= 10 * nDay
+ (*p
- '0');
436 eState
= STATE_ERROR
;
437 else if (*p
== '-' && nDay
&& nDay
<= 31)
440 eState
= STATE_2_YEAR
;
443 eState
= STATE_ERROR
;
447 if (*p
>= '0' && *p
<= '9')
451 nYear
= 10 * nYear
+ (*p
- '0');
455 eState
= STATE_ERROR
;
459 if (ascii_isWhitespace(*p
))
460 eState
= STATE_2_YEAR_LWS
;
462 eState
= STATE_ERROR
;
466 case STATE_2_YEAR_LWS
:
467 if (*p
>= '0' && *p
<= '9')
471 eState
= STATE_2_HOUR
;
473 else if (!ascii_isWhitespace(*p
))
474 eState
= STATE_ERROR
;
478 if (*p
>= '0' && *p
<= '9')
481 nHour
= 10 * nHour
+ (*p
- '0');
485 eState
= STATE_ERROR
;
486 else if (*p
== ':' && nHour
< 24)
489 eState
= STATE_2_MINUTE
;
492 eState
= STATE_ERROR
;
496 if (*p
>= '0' && *p
<= '9')
500 nMinute
= 10 * nMinute
+ (*p
- '0');
504 eState
= STATE_ERROR
;
508 if (ascii_isWhitespace(*p
) && (nMinute
< 60))
509 eState
= STATE_LWS_NAME
;
511 eState
= STATE_ERROR
;
516 if (!ascii_isWhitespace(*p
))
518 setPath (rEntry
.m_aName
, p
);
520 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
521 rEntry
.m_nSize
= nSize
;
523 setYear (rEntry
.m_aDate
, nYear
);
525 rEntry
.m_aDate
.SetMonth(nMonth
);
526 rEntry
.m_aDate
.SetDay(nDay
);
527 rEntry
.m_aDate
.SetHour(nHour
);
528 rEntry
.m_aDate
.SetMin(nMinute
);
543 * Directory entries may span one or two lines:
545 * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest
547 * name: filename "." filetype ";" version
548 * filename: 1*39fchar
549 * filetype: 1*39fchar
550 * version: non0digit *digit
552 * size: "0" / non0digit *digit
554 * datetime: date 1*lwsp time
555 * date: day "-" month "-" year
556 * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1")
557 * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG"
558 * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive
559 * year: 2digit / 4digit
560 * time: hour ":" minute
561 * hour: ((*1"0" / "1") digit) / ("2" "0"-"3")
562 * minute: "0"-"5" digit
564 * rest: *1(lws *<ANY>)
566 * lws: <TAB> / <SPACE>
568 * digit: "0" / non0digit
569 * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$"
571 * For directories, the returned name is the <filename> part; for non-
572 * directory files, the returned name is the <filename "." filetype> part.
573 * An entry is a directory iff its filetype is "DIR" (ignoring case).
575 * The READ, WRITE, and ISLINK mode bits are not supported.
577 * The returned size is the <size> part, multiplied by 512, and with the high
578 * order bits truncated to fit into a ULONG.
581 sal_Bool
FTPDirectoryParser::parseVMS (
583 const sal_Char
*pBuffer
)
585 static OUString aFirstLineName
;
586 static sal_Bool bFirstLineDir
= sal_False
;
588 for (sal_Bool bFirstLine
= sal_True
;; bFirstLine
= sal_False
)
590 const sal_Char
*p
= pBuffer
;
594 while (*p
== '\t' || *p
== ' ')
597 // Parse <filename "."> part:
598 const sal_Char
*pFileName
= p
;
599 while ((*p
>= 'A' && *p
<= 'Z') ||
600 (*p
>= 'a' && *p
<= 'z') ||
601 (*p
>= '0' && *p
<= '9') ||
602 *p
== '-' || *p
== '_' || *p
== '$')
605 if (*p
!= '.' || p
== pFileName
|| p
- pFileName
> 39)
607 if (aFirstLineName
.getLength())
613 // Parse <filetype ";"> part:
614 const sal_Char
*pFileType
= ++p
;
615 while ((*p
>= 'A' && *p
<= 'Z') ||
616 (*p
>= 'a' && *p
<= 'z') ||
617 (*p
>= '0' && *p
<= '9') ||
618 *p
== '-' || *p
== '_' || *p
== '$')
621 if (*p
!= ';' || p
== pFileName
|| p
- pFileName
> 39)
623 if (aFirstLineName
.getLength())
630 // Set entry's name and mode (ISDIR flag):
631 if ((p
- pFileType
== 4) &&
632 (pFileType
[0] == 'D' || pFileType
[0] == 'd') &&
633 (pFileType
[1] == 'I' || pFileType
[1] == 'i') &&
634 (pFileType
[2] == 'R' || pFileType
[2] == 'r') )
636 setPath (rEntry
.m_aName
, pFileName
, (pFileType
- pFileName
));
637 rEntry
.m_nMode
= INETCOREFTP_FILEMODE_ISDIR
;
641 setPath (rEntry
.m_aName
, pFileName
, (p
- pFileName
));
645 // Skip <version> part:
646 if (*p
< '1' || *p
> '9')
648 if (aFirstLineName
.getLength())
654 while (*p
>= '0' && *p
<= '9')
657 // Parse <1*lws> or <*lws <NEWLINE>> part:
658 sal_Bool bLWS
= false;
659 while (*p
== '\t' || *p
== ' ')
668 if (aFirstLineName
.getLength())
677 * First line of entry spanning two lines,
678 * wait for second line.
680 aFirstLineName
= rEntry
.m_aName
;
682 ((rEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
) != 0);
689 * Second line of entry spanning two lines,
690 * restore entry's name and mode (ISDIR flag).
692 rEntry
.m_aName
= aFirstLineName
;
693 rEntry
.m_nMode
= (bFirstLineDir
? INETCOREFTP_FILEMODE_ISDIR
: 0);
695 // Skip <1*lws> part:
696 if (*p
!= '\t' && *p
!= ' ')
699 while (*p
== '\t' || *p
== ' ')
703 // Parse <size> part and set entry's size:
704 if (*p
< '0' || *p
> '9')
706 ULONG nSize
= *p
- '0';
708 while (*p
>= '0' && *p
<= '9')
709 nSize
= 10 * rEntry
.m_nSize
+ (*p
++ - '0');
710 rEntry
.m_nSize
= 512 * nSize
;
712 // Skip <1*lws> part:
713 if (*p
!= '\t' && *p
!= ' ')
716 while (*p
== '\t' || *p
== ' ')
719 // Parse <day "-"> part and set entry date's day:
724 if (*p
< '1' || *p
> '9')
728 else if (*p
== '1' || *p
== '2')
731 if (*p
>= '0' && *p
<= '9')
732 nDay
= 10 * nDay
+ (*p
++ - '0');
737 nDay
= (*p
== '0' || *p
== '1') ? 30 + (*p
++ - '0') : 3;
739 else if (*p
>= '4' && *p
<= '9')
744 rEntry
.m_aDate
.SetDay(nDay
);
748 // Parse <month "-"> part and set entry date's month:
749 sal_Char
const * pMonth
= p
;
750 sal_Int32
const monthLen
= 3;
751 for (int i
= 0; i
< monthLen
; ++i
)
753 if (!((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z')))
757 if (rtl_str_compareIgnoreAsciiCase_WithLength(
758 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JAN")) == 0)
759 rEntry
.m_aDate
.SetMonth(1);
760 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
761 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("FEB")) == 0)
762 rEntry
.m_aDate
.SetMonth(2);
763 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
764 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("MAR")) == 0)
765 rEntry
.m_aDate
.SetMonth(3);
766 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
767 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("APR")) == 0)
768 rEntry
.m_aDate
.SetMonth(4);
769 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
770 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("MAY")) == 0)
771 rEntry
.m_aDate
.SetMonth(5);
772 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
773 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JUN")) == 0)
774 rEntry
.m_aDate
.SetMonth(6);
775 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
776 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JUL")) == 0)
777 rEntry
.m_aDate
.SetMonth(7);
778 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
779 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("AUG")) == 0)
780 rEntry
.m_aDate
.SetMonth(8);
781 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
782 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("SEP")) == 0)
783 rEntry
.m_aDate
.SetMonth(9);
784 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
785 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("OCT")) == 0)
786 rEntry
.m_aDate
.SetMonth(10);
787 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
788 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("NOV")) == 0)
789 rEntry
.m_aDate
.SetMonth(11);
790 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
791 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("DEC")) == 0)
792 rEntry
.m_aDate
.SetMonth(12);
798 // Parse <year> part and set entry date's year:
799 sal_uInt16 nYear
= 0;
800 {for (int i
= 0; i
< 2; ++i
)
802 if (*p
< '0' || *p
> '9')
804 nYear
= 10 * nYear
+ (*p
++ - '0');
806 if (*p
>= '0' && *p
<= '9')
808 nYear
= 10 * nYear
+ (*p
++ - '0');
809 if (*p
< '0' || *p
> '9')
811 nYear
= 10 * nYear
+ (*p
++ - '0');
813 setYear (rEntry
.m_aDate
, nYear
);
815 // Skip <1*lws> part:
816 if (*p
!= '\t' && *p
!= ' ')
819 while (*p
== '\t' || *p
== ' ')
822 // Parse <hour ":"> part and set entry time's hour:
824 if (*p
== '0' || *p
== '1')
827 if (*p
>= '0' && *p
<= '9')
828 nHour
= 10 * nHour
+ (*p
++ - '0');
833 nHour
= (*p
>= '0' && *p
<= '3') ? 20 + (*p
++ - '0') : 2;
835 else if (*p
>= '3' && *p
<= '9')
840 rEntry
.m_aDate
.SetHour(nHour
);
845 * Parse <minute> part and set entry time's minutes,
846 * seconds (0), and 1/100 seconds (0).
848 if (*p
< '0' || *p
> '5')
851 sal_uInt16 nMinute
= *p
++ - '0';
852 if (*p
< '0' || *p
> '9')
855 nMinute
= 10 * nMinute
+ (*p
++ - '0');
856 rEntry
.m_aDate
.SetMin(nMinute
);
857 rEntry
.m_aDate
.SetSec(0);
858 rEntry
.m_aDate
.Set100Sec(0);
861 if (*p
&& (*p
!= '\t' && *p
!= ' '))
871 sal_Bool
FTPDirectoryParser::parseUNIX (
873 const sal_Char
*pBuffer
)
875 const sal_Char
*p1
, *p2
;
878 if (!((*p1
== '-') || (*p1
== 'd') || (*p1
== 'l')))
881 // 1st column: FileMode.
883 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
886 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISLINK
;
888 // Skip to end of column and set rights by the way
889 while (*p1
&& !ascii_isWhitespace(*p1
)) {
891 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_READ
;
893 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_WRITE
;
898 * Scan for the sequence of size and date fields:
899 * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS
900 * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS
904 FOUND_NONE
, FOUND_SIZE
, FOUND_MONTH
, FOUND_DAY
, FOUND_YEAR_TIME
907 const sal_Char
*pDayStart
= 0;
908 const sal_Char
*pDayEnd
= 0;
910 for (eMode
= FOUND_NONE
; *p1
&& eMode
!= FOUND_YEAR_TIME
; p1
= p2
+ 1)
912 while (*p1
&& ascii_isWhitespace(*p1
))
915 while (*p2
&& !ascii_isWhitespace(*p2
))
921 if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
926 if (parseUNIX_isMonthField (p1
, p2
, rEntry
.m_aDate
))
928 else if (!parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
933 if (parseUNIX_isDayField (p1
, p2
, rEntry
.m_aDate
))
939 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
946 if (parseUNIX_isYearTimeField (p1
, p2
, rEntry
.m_aDate
))
947 eMode
= FOUND_YEAR_TIME
;
949 parseUNIX_isSizeField (
950 pDayStart
, pDayEnd
, rEntry
.m_nSize
) &&
951 parseUNIX_isMonthField (
952 p1
, p2
, rEntry
.m_aDate
))
954 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
959 case FOUND_YEAR_TIME
:
964 if (eMode
== FOUND_YEAR_TIME
)
966 // 9th column: FileName (rest of line).
967 while (*p1
&& ascii_isWhitespace(*p1
)) p1
++;
968 setPath (rEntry
.m_aName
, p1
);
979 sal_Bool
FTPDirectoryParser::parseUNKNOWN (
981 const sal_Char
*pBuffer
,
984 setPath (rEntry
.m_aName
, pBuffer
,sal_Int32 (nLength
));
989 * parseUNIX_isSizeField.
991 sal_Bool
FTPDirectoryParser::parseUNIX_isSizeField (
992 const sal_Char
*pStart
,
993 const sal_Char
*pEnd
,
996 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1000 if (*pStart
>= '0' && *pStart
<= '9')
1002 for (; pStart
< pEnd
; ++pStart
)
1003 if ((*pStart
>= '0') && (*pStart
<= '9'))
1004 rSize
= 10 * rSize
+ (*pStart
- '0');
1012 * For a combination of long group name and large file size,
1013 * some FTPDs omit LWS between those two columns.
1018 for (; pStart
< pEnd
; ++pStart
)
1019 if ((*pStart
>= '1') && (*pStart
<= '9'))
1022 rSize
= 10 * rSize
+ (*pStart
- '0');
1024 else if ((*pStart
== '0') && nDigits
)
1029 else if ((*pStart
> ' ') && (sal::static_int_cast
<sal_uInt8
>(*pStart
) <= '\x7F'))
1031 nNonDigits
+= nDigits
+ 1;
1037 return ((nNonDigits
>= 9) && (nDigits
>= 7));
1042 * parseUNIX_isMonthField.
1044 sal_Bool
FTPDirectoryParser::parseUNIX_isMonthField (
1045 const sal_Char
*pStart
,
1046 const sal_Char
*pEnd
,
1047 DateTime
&rDateTime
)
1049 if (!*pStart
|| !*pEnd
|| pStart
+ 3 != pEnd
)
1052 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1053 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1054 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1056 rDateTime
.SetMonth(1);
1059 if ((pStart
[0] == 'f' || pStart
[0] == 'F') &&
1060 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1061 (pStart
[2] == 'b' || pStart
[2] == 'B') )
1063 rDateTime
.SetMonth(2);
1066 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1067 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1068 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1070 rDateTime
.SetMonth(3);
1073 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1074 (pStart
[1] == 'p' || pStart
[1] == 'P') &&
1075 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1077 rDateTime
.SetMonth(4);
1080 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1081 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1082 (pStart
[2] == 'y' || pStart
[2] == 'Y') )
1084 rDateTime
.SetMonth(5);
1087 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1088 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1089 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1091 rDateTime
.SetMonth(6);
1094 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1095 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1096 (pStart
[2] == 'l' || pStart
[2] == 'L') )
1098 rDateTime
.SetMonth(7);
1101 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1102 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1103 (pStart
[2] == 'g' || pStart
[2] == 'G') )
1105 rDateTime
.SetMonth(8);
1108 if ((pStart
[0] == 's' || pStart
[0] == 'S') &&
1109 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1110 (pStart
[2] == 'p' || pStart
[2] == 'P') )
1112 rDateTime
.SetMonth(9);
1115 if ((pStart
[0] == 'o' || pStart
[0] == 'O') &&
1116 (pStart
[1] == 'c' || pStart
[1] == 'C') &&
1117 (pStart
[2] == 't' || pStart
[2] == 'T') )
1119 rDateTime
.SetMonth(10);
1122 if ((pStart
[0] == 'n' || pStart
[0] == 'N') &&
1123 (pStart
[1] == 'o' || pStart
[1] == 'O') &&
1124 (pStart
[2] == 'v' || pStart
[2] == 'V') )
1126 rDateTime
.SetMonth(11);
1129 if ((pStart
[0] == 'd' || pStart
[0] == 'D') &&
1130 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1131 (pStart
[2] == 'c' || pStart
[2] == 'C') )
1133 rDateTime
.SetMonth(12);
1140 * parseUNIX_isDayField.
1142 sal_Bool
FTPDirectoryParser::parseUNIX_isDayField (
1143 const sal_Char
*pStart
,
1144 const sal_Char
*pEnd
,
1145 DateTime
&rDateTime
)
1147 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1149 if (*pStart
< '0' || *pStart
> '9')
1152 sal_uInt16 nDay
= *pStart
- '0';
1153 if (pStart
+ 1 < pEnd
)
1155 if (pStart
+ 2 != pEnd
|| pStart
[1] < '0' || pStart
[1] > '9')
1157 nDay
= 10 * nDay
+ (pStart
[1] - '0');
1159 if (!nDay
|| nDay
> 31)
1162 rDateTime
.SetDay(nDay
);
1167 * parseUNIX_isYearTimeField.
1169 sal_Bool
FTPDirectoryParser::parseUNIX_isYearTimeField (
1170 const sal_Char
*pStart
,
1171 const sal_Char
*pEnd
,
1172 DateTime
&rDateTime
)
1174 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
||
1175 *pStart
< '0' || *pStart
> '9')
1178 sal_uInt16 nNumber
= *pStart
- '0';
1184 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1185 if (*pStart
< '0' || *pStart
> '9')
1188 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1194 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1195 if (*pStart
< '0' || *pStart
> '9')
1198 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1201 if (pStart
== pEnd
|| *pStart
< '0' || *pStart
> '9')
1204 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1205 if (pStart
+ 1 != pEnd
|| nNumber
< 1970)
1208 rDateTime
.SetYear(nNumber
);
1209 rDateTime
.SetTime(0);
1216 sal_Bool
FTPDirectoryParser::parseUNIX_isTime (
1217 const sal_Char
*pStart
,
1218 const sal_Char
*pEnd
,
1220 DateTime
&rDateTime
)
1222 if ((nHour
> 23 ) || (pStart
+ 3 != pEnd
) ||
1223 (pStart
[1] < '0') || (pStart
[1] > '5') ||
1224 (pStart
[2] < '0') || (pStart
[2] > '9') )
1227 sal_uInt16 nMin
= 10 * (pStart
[1] - '0') + (pStart
[2] - '0');
1229 rDateTime
.SetHour (nHour
);
1230 rDateTime
.SetMin (nMin
);
1231 rDateTime
.SetSec (0);
1232 rDateTime
.Set100Sec (0);
1235 // if (rDateTime.GetMonth() > aCurDate.GetMonth())
1236 // rDateTime.SetYear(aCurDate.GetYear() - 1);
1238 // rDateTime.SetYear(aCurDate.GetYear());
1242 osl_getSystemTime(&aTimeVal
);
1243 oslDateTime aCurrDateTime
;
1244 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1246 if (rDateTime
.GetMonth() > aCurrDateTime
.Month
)
1247 rDateTime
.SetYear(aCurrDateTime
.Year
- 1);
1249 rDateTime
.SetYear(aCurrDateTime
.Year
);
1256 * Two-digit years are taken as within 50 years back and 49 years forward
1257 * (both ends inclusive) from the current year. The returned date is not
1258 * checked for validity of the given day in the given month and year.
1261 sal_Bool
FTPDirectoryParser::setYear (
1262 DateTime
&rDateTime
, sal_uInt16 nYear
)
1267 osl_getSystemTime(&aTimeVal
);
1268 oslDateTime aCurrDateTime
;
1269 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1270 sal_uInt16 nCurrentYear
= aCurrDateTime
.Year
;
1271 // sal_uInt16 nCurrentYear = Date().GetYear();
1272 sal_uInt16 nCurrentCentury
= nCurrentYear
/ 100;
1273 nCurrentYear
%= 100;
1274 if (nCurrentYear
< 50)
1275 if (nYear
<= nCurrentYear
)
1276 nYear
+= nCurrentCentury
* 100;
1277 else if (nYear
< nCurrentYear
+ 50)
1278 nYear
+= nCurrentCentury
* 100;
1280 nYear
+= (nCurrentCentury
- 1) * 100;
1282 if (nYear
>= nCurrentYear
)
1283 nYear
+= nCurrentCentury
* 100;
1284 else if (nYear
>= nCurrentYear
- 50)
1285 nYear
+= nCurrentCentury
* 100;
1287 nYear
+= (nCurrentCentury
+ 1) * 100;
1290 rDateTime
.SetYear(nYear
);
1297 sal_Bool
FTPDirectoryParser::setPath (
1298 OUString
&rPath
, const sal_Char
*value
, sal_Int32 length
)
1303 length
= rtl_str_getLength (value
);
1304 rPath
= OUString (value
, length
, RTL_TEXTENCODING_UTF8
);