1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
26 #include "ftpdirp.hxx"
32 typedef sal_uInt32 ULONG
;
35 inline sal_Bool
ascii_isLetter( sal_Unicode ch
)
37 return (( (ch
>= 0x0041) && (ch
<= 0x005A)) ||
38 (( ch
>= 0x0061) && (ch
<= 0x007A)));
41 inline sal_Bool
ascii_isWhitespace( sal_Unicode ch
)
43 return ((ch
<= 0x20) && ch
);
48 /*========================================================================
50 * FTPDirectoryParser implementation.
52 *======================================================================*/
55 * Accepts one of two styles:
57 * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP
58 * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP
59 * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET
61 * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name
63 * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT
64 * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET
66 * interpreted as: size attribs DIR mm-dd-yy hh:mm name
69 sal_Bool
FTPDirectoryParser::parseDOS (
71 const sal_Char
*pBuffer
)
73 sal_Bool bDirectory
= false;
76 sal_uInt16 nMonth
= 0;
79 sal_uInt16 nMinute
= 0;
85 STATE_1_DAY
, STATE_1_YEAR
, STATE_1_YEAR_LWS
, STATE_1_HOUR
,
86 STATE_1_MINUTE
, STATE_1_MINUTE_LWS
, STATE_1_AP
,
87 STATE_1_APM
, STATE_1_LESS
, STATE_1_D
, STATE_1_DI
,
88 STATE_1_DIR
, STATE_1_SIZE
,
89 STATE_2_SIZE
, STATE_2_SIZE_LWS
, STATE_2_ATTRIB
,
90 STATE_2_D
, STATE_2_DI
, STATE_2_DIR_LWS
,
91 STATE_2_MONTH
, STATE_2_DAY
, STATE_2_YEAR
, STATE_2_YEAR_LWS
,
92 STATE_2_HOUR
, STATE_2_MINUTE
,
98 enum StateType eState
= STATE_INIT_LWS
;
99 for (const sal_Char
*p
= pBuffer
;
100 eState
!= STATE_ERROR
&& *p
;
106 if (*p
>= '0' && *p
<= '9')
110 eState
= STATE_MONTH_OR_SIZE
;
112 else if (!ascii_isWhitespace(*p
))
113 eState
= STATE_ERROR
;
116 case STATE_MONTH_OR_SIZE
:
117 if (*p
>= '0' && *p
<= '9')
119 nMonth
= 10 * nMonth
+ (*p
- '0');
126 eState
= STATE_2_SIZE
;
129 else if (ascii_isWhitespace(*p
))
133 eState
= STATE_2_SIZE_LWS
;
135 else if ((*p
== '.' || *p
== '-') && nMonth
&& nMonth
<= 12)
138 eState
= STATE_1_DAY
;
141 eState
= STATE_ERROR
;
145 if (*p
>= '0' && *p
<= '9')
148 nDay
= 10 * nDay
+ (*p
- '0');
152 eState
= STATE_ERROR
;
153 else if ((*p
== '.' || *p
== '-') && nDay
&& nDay
<= 31)
156 eState
= STATE_1_YEAR
;
159 eState
= STATE_ERROR
;
163 if (*p
>= '0' && *p
<= '9')
167 nYear
= 10 * nYear
+ (*p
- '0');
171 eState
= STATE_ERROR
;
175 if (ascii_isWhitespace(*p
))
176 eState
= STATE_1_YEAR_LWS
;
178 eState
= STATE_ERROR
;
182 case STATE_1_YEAR_LWS
:
183 if (*p
>= '0' && *p
<= '9')
187 eState
= STATE_1_HOUR
;
189 else if (!ascii_isWhitespace(*p
))
190 eState
= STATE_ERROR
;
194 if (*p
>= '0' && *p
<= '9')
197 nHour
= 10 * nHour
+ (*p
- '0');
201 eState
= STATE_ERROR
;
202 else if (*p
== ':' && nHour
< 24)
205 eState
= STATE_1_MINUTE
;
208 eState
= STATE_ERROR
;
212 if (*p
>= '0' && *p
<= '9')
215 nMinute
= 10 * nMinute
+ (*p
- '0');
219 eState
= STATE_ERROR
;
220 else if ((*p
== 'a' || *p
== 'A') && nMinute
< 60)
221 if (nHour
>= 1 && nHour
<= 11)
223 else if (nHour
== 12)
229 eState
= STATE_ERROR
;
230 else if ((*p
== 'p' || *p
== 'P') && nMinute
< 60)
231 if (nHour
>= 1 && nHour
<= 11)
236 else if (nHour
== 12)
239 eState
= STATE_ERROR
;
240 else if (ascii_isWhitespace(*p
) && (nMinute
< 60))
241 eState
= STATE_1_MINUTE_LWS
;
243 eState
= STATE_ERROR
;
246 case STATE_1_MINUTE_LWS
:
247 if (*p
== 'a' || *p
== 'A')
248 if (nHour
>= 1 && nHour
<= 11)
250 else if (nHour
== 12)
256 eState
= STATE_ERROR
;
257 else if (*p
== 'p' || *p
== 'P')
258 if (nHour
>= 1 && nHour
<= 11)
263 else if (nHour
== 12)
266 eState
= STATE_ERROR
;
268 eState
= STATE_1_LESS
;
269 else if (*p
>= '0' && *p
<= '9')
272 eState
= STATE_1_SIZE
;
274 else if (!ascii_isWhitespace(*p
))
275 eState
= STATE_ERROR
;
279 eState
= *p
== 'm' || *p
== 'M' ? STATE_1_APM
: STATE_ERROR
;
284 eState
= STATE_1_LESS
;
285 else if (*p
>= '0' && *p
<= '9')
288 eState
= STATE_1_SIZE
;
290 else if (!ascii_isWhitespace(*p
))
291 eState
= STATE_ERROR
;
295 eState
= *p
== 'd' || *p
== 'D' ? STATE_1_D
: STATE_ERROR
;
299 eState
= *p
== 'i' || *p
== 'I' ? STATE_1_DI
: STATE_ERROR
;
303 eState
= *p
== 'r' || *p
== 'R' ? STATE_1_DIR
: STATE_ERROR
;
310 eState
= STATE_LWS_NAME
;
313 eState
= STATE_ERROR
;
317 if (*p
>= '0' && *p
<= '9')
318 nSize
= 10 * nSize
+ (*p
- '0');
319 else if (ascii_isWhitespace(*p
))
320 eState
= STATE_LWS_NAME
;
322 eState
= STATE_ERROR
;
326 if (*p
>= '0' && *p
<= '9')
327 nSize
= 10 * nSize
+ (*p
- '0');
328 else if (ascii_isWhitespace(*p
))
329 eState
= STATE_2_SIZE_LWS
;
331 eState
= STATE_ERROR
;
334 case STATE_2_SIZE_LWS
:
335 if (*p
== 'd' || *p
== 'D')
337 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
338 eState
= STATE_2_ATTRIB
;
339 else if (*p
>= '0' && *p
<= '9')
343 eState
= STATE_2_MONTH
;
345 else if (!ascii_isWhitespace(*p
))
346 eState
= STATE_ERROR
;
350 if (ascii_isWhitespace(*p
))
351 eState
= STATE_2_SIZE_LWS
;
352 else if ((*p
< 'a' || *p
> 'z') && (*p
< 'A' || *p
> 'Z'))
353 eState
= STATE_ERROR
;
357 if (*p
== 'i' || *p
== 'I')
359 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
360 eState
= STATE_2_ATTRIB
;
361 else if (ascii_isWhitespace(*p
))
362 eState
= STATE_2_SIZE_LWS
;
364 eState
= STATE_ERROR
;
368 if (*p
== 'r' || *p
== 'R')
371 eState
= STATE_2_DIR_LWS
;
375 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
376 eState
= STATE_2_ATTRIB
;
377 else if (ascii_isWhitespace(*p
))
378 eState
= STATE_2_SIZE_LWS
;
380 eState
= STATE_ERROR
;
384 case STATE_2_DIR_LWS
:
385 if (*p
>= '0' && *p
<= '9')
389 eState
= STATE_2_MONTH
;
391 else if (!ascii_isWhitespace(*p
))
392 eState
= STATE_ERROR
;
396 if (*p
>= '0' && *p
<= '9')
399 nMonth
= 10 * nMonth
+ (*p
- '0');
403 eState
= STATE_ERROR
;
404 else if (*p
== '-' && nMonth
&& nMonth
<= 12)
407 eState
= STATE_2_DAY
;
410 eState
= STATE_ERROR
;
414 if (*p
>= '0' && *p
<= '9')
417 nDay
= 10 * nDay
+ (*p
- '0');
421 eState
= STATE_ERROR
;
422 else if (*p
== '-' && nDay
&& nDay
<= 31)
425 eState
= STATE_2_YEAR
;
428 eState
= STATE_ERROR
;
432 if (*p
>= '0' && *p
<= '9')
436 nYear
= 10 * nYear
+ (*p
- '0');
440 eState
= STATE_ERROR
;
444 if (ascii_isWhitespace(*p
))
445 eState
= STATE_2_YEAR_LWS
;
447 eState
= STATE_ERROR
;
451 case STATE_2_YEAR_LWS
:
452 if (*p
>= '0' && *p
<= '9')
456 eState
= STATE_2_HOUR
;
458 else if (!ascii_isWhitespace(*p
))
459 eState
= STATE_ERROR
;
463 if (*p
>= '0' && *p
<= '9')
466 nHour
= 10 * nHour
+ (*p
- '0');
470 eState
= STATE_ERROR
;
471 else if (*p
== ':' && nHour
< 24)
474 eState
= STATE_2_MINUTE
;
477 eState
= STATE_ERROR
;
481 if (*p
>= '0' && *p
<= '9')
485 nMinute
= 10 * nMinute
+ (*p
- '0');
489 eState
= STATE_ERROR
;
493 if (ascii_isWhitespace(*p
) && (nMinute
< 60))
494 eState
= STATE_LWS_NAME
;
496 eState
= STATE_ERROR
;
501 if (!ascii_isWhitespace(*p
))
503 setPath (rEntry
.m_aName
, p
);
505 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
506 rEntry
.m_nSize
= nSize
;
508 setYear (rEntry
.m_aDate
, nYear
);
510 rEntry
.m_aDate
.SetMonth(nMonth
);
511 rEntry
.m_aDate
.SetDay(nDay
);
512 rEntry
.m_aDate
.SetHour(nHour
);
513 rEntry
.m_aDate
.SetMin(nMinute
);
528 * Directory entries may span one or two lines:
530 * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest
532 * name: filename "." filetype ";" version
533 * filename: 1*39fchar
534 * filetype: 1*39fchar
535 * version: non0digit *digit
537 * size: "0" / non0digit *digit
539 * datetime: date 1*lwsp time
540 * date: day "-" month "-" year
541 * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1")
542 * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG"
543 * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive
544 * year: 2digit / 4digit
545 * time: hour ":" minute
546 * hour: ((*1"0" / "1") digit) / ("2" "0"-"3")
547 * minute: "0"-"5" digit
549 * rest: *1(lws *<ANY>)
551 * lws: <TAB> / <SPACE>
553 * digit: "0" / non0digit
554 * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$"
556 * For directories, the returned name is the <filename> part; for non-
557 * directory files, the returned name is the <filename "." filetype> part.
558 * An entry is a directory iff its filetype is "DIR" (ignoring case).
560 * The READ, WRITE, and ISLINK mode bits are not supported.
562 * The returned size is the <size> part, multiplied by 512, and with the high
563 * order bits truncated to fit into a ULONG.
566 sal_Bool
FTPDirectoryParser::parseVMS (
568 const sal_Char
*pBuffer
)
570 static OUString aFirstLineName
;
571 static sal_Bool bFirstLineDir
= sal_False
;
573 for (sal_Bool bFirstLine
= sal_True
;; bFirstLine
= sal_False
)
575 const sal_Char
*p
= pBuffer
;
579 while (*p
== '\t' || *p
== ' ')
582 // Parse <filename "."> part:
583 const sal_Char
*pFileName
= p
;
584 while ((*p
>= 'A' && *p
<= 'Z') ||
585 (*p
>= 'a' && *p
<= 'z') ||
586 (*p
>= '0' && *p
<= '9') ||
587 *p
== '-' || *p
== '_' || *p
== '$')
590 if (*p
!= '.' || p
== pFileName
|| p
- pFileName
> 39)
592 if (!aFirstLineName
.isEmpty())
598 // Parse <filetype ";"> part:
599 const sal_Char
*pFileType
= ++p
;
600 while ((*p
>= 'A' && *p
<= 'Z') ||
601 (*p
>= 'a' && *p
<= 'z') ||
602 (*p
>= '0' && *p
<= '9') ||
603 *p
== '-' || *p
== '_' || *p
== '$')
606 if (*p
!= ';' || p
== pFileName
|| p
- pFileName
> 39)
608 if (!aFirstLineName
.isEmpty())
615 // Set entry's name and mode (ISDIR flag):
616 if ((p
- pFileType
== 4) &&
617 (pFileType
[0] == 'D' || pFileType
[0] == 'd') &&
618 (pFileType
[1] == 'I' || pFileType
[1] == 'i') &&
619 (pFileType
[2] == 'R' || pFileType
[2] == 'r') )
621 setPath (rEntry
.m_aName
, pFileName
, (pFileType
- pFileName
));
622 rEntry
.m_nMode
= INETCOREFTP_FILEMODE_ISDIR
;
626 setPath (rEntry
.m_aName
, pFileName
, (p
- pFileName
));
630 // Skip <version> part:
631 if (*p
< '1' || *p
> '9')
633 if (!aFirstLineName
.isEmpty())
639 while (*p
>= '0' && *p
<= '9')
642 // Parse <1*lws> or <*lws <NEWLINE>> part:
643 sal_Bool bLWS
= false;
644 while (*p
== '\t' || *p
== ' ')
653 if (!aFirstLineName
.isEmpty())
662 * First line of entry spanning two lines,
663 * wait for second line.
665 aFirstLineName
= rEntry
.m_aName
;
667 ((rEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
) != 0);
674 * Second line of entry spanning two lines,
675 * restore entry's name and mode (ISDIR flag).
677 rEntry
.m_aName
= aFirstLineName
;
678 rEntry
.m_nMode
= (bFirstLineDir
? INETCOREFTP_FILEMODE_ISDIR
: 0);
680 // Skip <1*lws> part:
681 if (*p
!= '\t' && *p
!= ' ')
684 while (*p
== '\t' || *p
== ' ')
688 // Parse <size> part and set entry's size:
689 if (*p
< '0' || *p
> '9')
691 ULONG nSize
= *p
- '0';
693 while (*p
>= '0' && *p
<= '9')
694 nSize
= 10 * rEntry
.m_nSize
+ (*p
++ - '0');
695 rEntry
.m_nSize
= 512 * nSize
;
697 // Skip <1*lws> part:
698 if (*p
!= '\t' && *p
!= ' ')
701 while (*p
== '\t' || *p
== ' ')
704 // Parse <day "-"> part and set entry date's day:
709 if (*p
< '1' || *p
> '9')
713 else if (*p
== '1' || *p
== '2')
716 if (*p
>= '0' && *p
<= '9')
717 nDay
= 10 * nDay
+ (*p
++ - '0');
722 nDay
= (*p
== '0' || *p
== '1') ? 30 + (*p
++ - '0') : 3;
724 else if (*p
>= '4' && *p
<= '9')
729 rEntry
.m_aDate
.SetDay(nDay
);
733 // Parse <month "-"> part and set entry date's month:
734 sal_Char
const * pMonth
= p
;
735 sal_Int32
const monthLen
= 3;
736 for (int i
= 0; i
< monthLen
; ++i
)
738 if (!((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z')))
742 if (rtl_str_compareIgnoreAsciiCase_WithLength(
743 pMonth
, monthLen
, "JAN", monthLen
) == 0)
744 rEntry
.m_aDate
.SetMonth(1);
745 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
746 pMonth
, monthLen
, "FEB", monthLen
) == 0)
747 rEntry
.m_aDate
.SetMonth(2);
748 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
749 pMonth
, monthLen
, "MAR", monthLen
) == 0)
750 rEntry
.m_aDate
.SetMonth(3);
751 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
752 pMonth
, monthLen
, "APR", monthLen
) == 0)
753 rEntry
.m_aDate
.SetMonth(4);
754 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
755 pMonth
, monthLen
, "MAY", monthLen
) == 0)
756 rEntry
.m_aDate
.SetMonth(5);
757 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
758 pMonth
, monthLen
, "JUN", monthLen
) == 0)
759 rEntry
.m_aDate
.SetMonth(6);
760 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
761 pMonth
, monthLen
, "JUL", monthLen
) == 0)
762 rEntry
.m_aDate
.SetMonth(7);
763 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
764 pMonth
, monthLen
, "AUG", monthLen
) == 0)
765 rEntry
.m_aDate
.SetMonth(8);
766 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
767 pMonth
, monthLen
, "SEP", monthLen
) == 0)
768 rEntry
.m_aDate
.SetMonth(9);
769 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
770 pMonth
, monthLen
, "OCT", monthLen
) == 0)
771 rEntry
.m_aDate
.SetMonth(10);
772 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
773 pMonth
, monthLen
, "NOV", monthLen
) == 0)
774 rEntry
.m_aDate
.SetMonth(11);
775 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
776 pMonth
, monthLen
, "DEC", monthLen
) == 0)
777 rEntry
.m_aDate
.SetMonth(12);
783 // Parse <year> part and set entry date's year:
784 sal_uInt16 nYear
= 0;
785 for (int i
= 0; i
< 2; ++i
)
787 if (*p
< '0' || *p
> '9')
789 nYear
= 10 * nYear
+ (*p
++ - '0');
791 if (*p
>= '0' && *p
<= '9')
793 nYear
= 10 * nYear
+ (*p
++ - '0');
794 if (*p
< '0' || *p
> '9')
796 nYear
= 10 * nYear
+ (*p
++ - '0');
798 setYear (rEntry
.m_aDate
, nYear
);
800 // Skip <1*lws> part:
801 if (*p
!= '\t' && *p
!= ' ')
804 while (*p
== '\t' || *p
== ' ')
807 // Parse <hour ":"> part and set entry time's hour:
809 if (*p
== '0' || *p
== '1')
812 if (*p
>= '0' && *p
<= '9')
813 nHour
= 10 * nHour
+ (*p
++ - '0');
818 nHour
= (*p
>= '0' && *p
<= '3') ? 20 + (*p
++ - '0') : 2;
820 else if (*p
>= '3' && *p
<= '9')
825 rEntry
.m_aDate
.SetHour(nHour
);
830 * Parse <minute> part and set entry time's minutes,
831 * seconds (0), and nanoseconds (0).
833 if (*p
< '0' || *p
> '5')
836 sal_uInt16 nMinute
= *p
++ - '0';
837 if (*p
< '0' || *p
> '9')
840 nMinute
= 10 * nMinute
+ (*p
++ - '0');
841 rEntry
.m_aDate
.SetMin(nMinute
);
842 rEntry
.m_aDate
.SetSec(0);
843 rEntry
.m_aDate
.SetNanoSec(0);
846 if (*p
&& (*p
!= '\t' && *p
!= ' '))
856 sal_Bool
FTPDirectoryParser::parseUNIX (
858 const sal_Char
*pBuffer
)
860 const sal_Char
*p1
, *p2
;
863 if (!((*p1
== '-') || (*p1
== 'd') || (*p1
== 'l')))
866 // 1st column: FileMode.
868 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
871 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISLINK
;
873 // Skip to end of column and set rights by the way
874 while (*p1
&& !ascii_isWhitespace(*p1
)) {
876 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_READ
;
878 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_WRITE
;
883 * Scan for the sequence of size and date fields:
884 * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS
885 * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS
889 FOUND_NONE
, FOUND_SIZE
, FOUND_MONTH
, FOUND_DAY
, FOUND_YEAR_TIME
892 const sal_Char
*pDayStart
= 0;
893 const sal_Char
*pDayEnd
= 0;
895 for (eMode
= FOUND_NONE
; *p1
&& eMode
!= FOUND_YEAR_TIME
; p1
= p2
+ 1)
897 while (*p1
&& ascii_isWhitespace(*p1
))
900 while (*p2
&& !ascii_isWhitespace(*p2
))
906 if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
911 if (parseUNIX_isMonthField (p1
, p2
, rEntry
.m_aDate
))
913 else if (!parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
918 if (parseUNIX_isDayField (p1
, p2
, rEntry
.m_aDate
))
924 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
931 if (parseUNIX_isYearTimeField (p1
, p2
, rEntry
.m_aDate
))
932 eMode
= FOUND_YEAR_TIME
;
934 parseUNIX_isSizeField (
935 pDayStart
, pDayEnd
, rEntry
.m_nSize
) &&
936 parseUNIX_isMonthField (
937 p1
, p2
, rEntry
.m_aDate
))
939 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
944 case FOUND_YEAR_TIME
:
949 if (eMode
== FOUND_YEAR_TIME
)
951 // 9th column: FileName (rest of line).
952 while (*p1
&& ascii_isWhitespace(*p1
)) p1
++;
953 setPath (rEntry
.m_aName
, p1
);
962 * parseUNIX_isSizeField.
964 sal_Bool
FTPDirectoryParser::parseUNIX_isSizeField (
965 const sal_Char
*pStart
,
966 const sal_Char
*pEnd
,
969 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
973 if (*pStart
>= '0' && *pStart
<= '9')
975 for (; pStart
< pEnd
; ++pStart
)
976 if ((*pStart
>= '0') && (*pStart
<= '9'))
977 rSize
= 10 * rSize
+ (*pStart
- '0');
985 * For a combination of long group name and large file size,
986 * some FTPDs omit LWS between those two columns.
991 for (; pStart
< pEnd
; ++pStart
)
992 if ((*pStart
>= '1') && (*pStart
<= '9'))
995 rSize
= 10 * rSize
+ (*pStart
- '0');
997 else if ((*pStart
== '0') && nDigits
)
1002 else if ((*pStart
> ' ') && (sal::static_int_cast
<sal_uInt8
>(*pStart
) <= '\x7F'))
1004 nNonDigits
+= nDigits
+ 1;
1010 return ((nNonDigits
>= 9) && (nDigits
>= 7));
1015 * parseUNIX_isMonthField.
1017 sal_Bool
FTPDirectoryParser::parseUNIX_isMonthField (
1018 const sal_Char
*pStart
,
1019 const sal_Char
*pEnd
,
1020 DateTime
&rDateTime
)
1022 if (!*pStart
|| !*pEnd
|| pStart
+ 3 != pEnd
)
1025 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1026 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1027 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1029 rDateTime
.SetMonth(1);
1032 if ((pStart
[0] == 'f' || pStart
[0] == 'F') &&
1033 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1034 (pStart
[2] == 'b' || pStart
[2] == 'B') )
1036 rDateTime
.SetMonth(2);
1039 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1040 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1041 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1043 rDateTime
.SetMonth(3);
1046 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1047 (pStart
[1] == 'p' || pStart
[1] == 'P') &&
1048 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1050 rDateTime
.SetMonth(4);
1053 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1054 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1055 (pStart
[2] == 'y' || pStart
[2] == 'Y') )
1057 rDateTime
.SetMonth(5);
1060 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1061 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1062 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1064 rDateTime
.SetMonth(6);
1067 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1068 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1069 (pStart
[2] == 'l' || pStart
[2] == 'L') )
1071 rDateTime
.SetMonth(7);
1074 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1075 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1076 (pStart
[2] == 'g' || pStart
[2] == 'G') )
1078 rDateTime
.SetMonth(8);
1081 if ((pStart
[0] == 's' || pStart
[0] == 'S') &&
1082 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1083 (pStart
[2] == 'p' || pStart
[2] == 'P') )
1085 rDateTime
.SetMonth(9);
1088 if ((pStart
[0] == 'o' || pStart
[0] == 'O') &&
1089 (pStart
[1] == 'c' || pStart
[1] == 'C') &&
1090 (pStart
[2] == 't' || pStart
[2] == 'T') )
1092 rDateTime
.SetMonth(10);
1095 if ((pStart
[0] == 'n' || pStart
[0] == 'N') &&
1096 (pStart
[1] == 'o' || pStart
[1] == 'O') &&
1097 (pStart
[2] == 'v' || pStart
[2] == 'V') )
1099 rDateTime
.SetMonth(11);
1102 if ((pStart
[0] == 'd' || pStart
[0] == 'D') &&
1103 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1104 (pStart
[2] == 'c' || pStart
[2] == 'C') )
1106 rDateTime
.SetMonth(12);
1113 * parseUNIX_isDayField.
1115 sal_Bool
FTPDirectoryParser::parseUNIX_isDayField (
1116 const sal_Char
*pStart
,
1117 const sal_Char
*pEnd
,
1118 DateTime
&rDateTime
)
1120 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1122 if (*pStart
< '0' || *pStart
> '9')
1125 sal_uInt16 nDay
= *pStart
- '0';
1126 if (pStart
+ 1 < pEnd
)
1128 if (pStart
+ 2 != pEnd
|| pStart
[1] < '0' || pStart
[1] > '9')
1130 nDay
= 10 * nDay
+ (pStart
[1] - '0');
1132 if (!nDay
|| nDay
> 31)
1135 rDateTime
.SetDay(nDay
);
1140 * parseUNIX_isYearTimeField.
1142 sal_Bool
FTPDirectoryParser::parseUNIX_isYearTimeField (
1143 const sal_Char
*pStart
,
1144 const sal_Char
*pEnd
,
1145 DateTime
&rDateTime
)
1147 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
||
1148 *pStart
< '0' || *pStart
> '9')
1151 sal_uInt16 nNumber
= *pStart
- '0';
1157 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1158 if (*pStart
< '0' || *pStart
> '9')
1161 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1167 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1168 if (*pStart
< '0' || *pStart
> '9')
1171 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1174 if (pStart
== pEnd
|| *pStart
< '0' || *pStart
> '9')
1177 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1178 if (pStart
+ 1 != pEnd
|| nNumber
< 1970)
1181 rDateTime
.SetYear(nNumber
);
1182 rDateTime
.SetTime(0);
1189 sal_Bool
FTPDirectoryParser::parseUNIX_isTime (
1190 const sal_Char
*pStart
,
1191 const sal_Char
*pEnd
,
1193 DateTime
&rDateTime
)
1195 if ((nHour
> 23 ) || (pStart
+ 3 != pEnd
) ||
1196 (pStart
[1] < '0') || (pStart
[1] > '5') ||
1197 (pStart
[2] < '0') || (pStart
[2] > '9') )
1200 sal_uInt16 nMin
= 10 * (pStart
[1] - '0') + (pStart
[2] - '0');
1202 rDateTime
.SetHour (nHour
);
1203 rDateTime
.SetMin (nMin
);
1204 rDateTime
.SetSec (0);
1205 rDateTime
.SetNanoSec (0);
1208 // if (rDateTime.GetMonth() > aCurDate.GetMonth())
1209 // rDateTime.SetYear(aCurDate.GetYear() - 1);
1211 // rDateTime.SetYear(aCurDate.GetYear());
1215 osl_getSystemTime(&aTimeVal
);
1216 oslDateTime aCurrDateTime
;
1217 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1219 if (rDateTime
.GetMonth() > aCurrDateTime
.Month
)
1220 rDateTime
.SetYear(aCurrDateTime
.Year
- 1);
1222 rDateTime
.SetYear(aCurrDateTime
.Year
);
1229 * Two-digit years are taken as within 50 years back and 49 years forward
1230 * (both ends inclusive) from the current year. The returned date is not
1231 * checked for validity of the given day in the given month and year.
1234 sal_Bool
FTPDirectoryParser::setYear (
1235 DateTime
&rDateTime
, sal_uInt16 nYear
)
1240 osl_getSystemTime(&aTimeVal
);
1241 oslDateTime aCurrDateTime
;
1242 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1243 sal_uInt16 nCurrentYear
= aCurrDateTime
.Year
;
1244 // sal_uInt16 nCurrentYear = Date().GetYear();
1245 sal_uInt16 nCurrentCentury
= nCurrentYear
/ 100;
1246 nCurrentYear
%= 100;
1247 if (nCurrentYear
< 50)
1248 if (nYear
<= nCurrentYear
)
1249 nYear
+= nCurrentCentury
* 100;
1250 else if (nYear
< nCurrentYear
+ 50)
1251 nYear
+= nCurrentCentury
* 100;
1253 nYear
+= (nCurrentCentury
- 1) * 100;
1255 if (nYear
>= nCurrentYear
)
1256 nYear
+= nCurrentCentury
* 100;
1257 else if (nYear
>= nCurrentYear
- 50)
1258 nYear
+= nCurrentCentury
* 100;
1260 nYear
+= (nCurrentCentury
+ 1) * 100;
1263 rDateTime
.SetYear(nYear
);
1270 sal_Bool
FTPDirectoryParser::setPath (
1271 OUString
&rPath
, const sal_Char
*value
, sal_Int32 length
)
1276 length
= rtl_str_getLength (value
);
1277 rPath
= OUString (value
, length
, RTL_TEXTENCODING_UTF8
);
1282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */