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
;
34 inline bool ascii_isWhitespace( sal_Unicode ch
)
36 return ((ch
<= 0x20) && ch
);
41 /*========================================================================
43 * FTPDirectoryParser implementation.
45 *======================================================================*/
48 * Accepts one of two styles:
50 * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP
51 * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP
52 * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET
54 * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name
56 * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT
57 * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET
59 * interpreted as: size attribs DIR mm-dd-yy hh:mm name
62 bool FTPDirectoryParser::parseDOS (
64 const sal_Char
*pBuffer
)
66 bool bDirectory
= false;
69 sal_uInt16 nMonth
= 0;
72 sal_uInt16 nMinute
= 0;
78 STATE_1_DAY
, STATE_1_YEAR
, STATE_1_YEAR_LWS
, STATE_1_HOUR
,
79 STATE_1_MINUTE
, STATE_1_MINUTE_LWS
, STATE_1_AP
,
80 STATE_1_APM
, STATE_1_LESS
, STATE_1_D
, STATE_1_DI
,
81 STATE_1_DIR
, STATE_1_SIZE
,
82 STATE_2_SIZE
, STATE_2_SIZE_LWS
, STATE_2_ATTRIB
,
83 STATE_2_D
, STATE_2_DI
, STATE_2_DIR_LWS
,
84 STATE_2_MONTH
, STATE_2_DAY
, STATE_2_YEAR
, STATE_2_YEAR_LWS
,
85 STATE_2_HOUR
, STATE_2_MINUTE
,
91 enum StateType eState
= STATE_INIT_LWS
;
92 for (const sal_Char
*p
= pBuffer
;
93 eState
!= STATE_ERROR
&& *p
;
99 if (*p
>= '0' && *p
<= '9')
103 eState
= STATE_MONTH_OR_SIZE
;
105 else if (!ascii_isWhitespace(*p
))
106 eState
= STATE_ERROR
;
109 case STATE_MONTH_OR_SIZE
:
110 if (*p
>= '0' && *p
<= '9')
112 nMonth
= 10 * nMonth
+ (*p
- '0');
119 eState
= STATE_2_SIZE
;
122 else if (ascii_isWhitespace(*p
))
126 eState
= STATE_2_SIZE_LWS
;
128 else if ((*p
== '.' || *p
== '-') && nMonth
&& nMonth
<= 12)
131 eState
= STATE_1_DAY
;
134 eState
= STATE_ERROR
;
138 if (*p
>= '0' && *p
<= '9')
141 nDay
= 10 * nDay
+ (*p
- '0');
145 eState
= STATE_ERROR
;
146 else if ((*p
== '.' || *p
== '-') && nDay
&& nDay
<= 31)
149 eState
= STATE_1_YEAR
;
152 eState
= STATE_ERROR
;
156 if (*p
>= '0' && *p
<= '9')
160 nYear
= 10 * nYear
+ (*p
- '0');
164 eState
= STATE_ERROR
;
168 if (ascii_isWhitespace(*p
))
169 eState
= STATE_1_YEAR_LWS
;
171 eState
= STATE_ERROR
;
175 case STATE_1_YEAR_LWS
:
176 if (*p
>= '0' && *p
<= '9')
180 eState
= STATE_1_HOUR
;
182 else if (!ascii_isWhitespace(*p
))
183 eState
= STATE_ERROR
;
187 if (*p
>= '0' && *p
<= '9')
190 nHour
= 10 * nHour
+ (*p
- '0');
194 eState
= STATE_ERROR
;
195 else if (*p
== ':' && nHour
< 24)
198 eState
= STATE_1_MINUTE
;
201 eState
= STATE_ERROR
;
205 if (*p
>= '0' && *p
<= '9')
208 nMinute
= 10 * nMinute
+ (*p
- '0');
212 eState
= STATE_ERROR
;
213 else if ((*p
== 'a' || *p
== 'A') && nMinute
< 60)
214 if (nHour
>= 1 && nHour
<= 11)
216 else if (nHour
== 12)
222 eState
= STATE_ERROR
;
223 else if ((*p
== 'p' || *p
== 'P') && nMinute
< 60)
224 if (nHour
>= 1 && nHour
<= 11)
229 else if (nHour
== 12)
232 eState
= STATE_ERROR
;
233 else if (ascii_isWhitespace(*p
) && (nMinute
< 60))
234 eState
= STATE_1_MINUTE_LWS
;
236 eState
= STATE_ERROR
;
239 case STATE_1_MINUTE_LWS
:
240 if (*p
== 'a' || *p
== 'A')
241 if (nHour
>= 1 && nHour
<= 11)
243 else if (nHour
== 12)
249 eState
= STATE_ERROR
;
250 else if (*p
== 'p' || *p
== 'P')
251 if (nHour
>= 1 && nHour
<= 11)
256 else if (nHour
== 12)
259 eState
= STATE_ERROR
;
261 eState
= STATE_1_LESS
;
262 else if (*p
>= '0' && *p
<= '9')
265 eState
= STATE_1_SIZE
;
267 else if (!ascii_isWhitespace(*p
))
268 eState
= STATE_ERROR
;
272 eState
= *p
== 'm' || *p
== 'M' ? STATE_1_APM
: STATE_ERROR
;
277 eState
= STATE_1_LESS
;
278 else if (*p
>= '0' && *p
<= '9')
281 eState
= STATE_1_SIZE
;
283 else if (!ascii_isWhitespace(*p
))
284 eState
= STATE_ERROR
;
288 eState
= *p
== 'd' || *p
== 'D' ? STATE_1_D
: STATE_ERROR
;
292 eState
= *p
== 'i' || *p
== 'I' ? STATE_1_DI
: STATE_ERROR
;
296 eState
= *p
== 'r' || *p
== 'R' ? STATE_1_DIR
: STATE_ERROR
;
303 eState
= STATE_LWS_NAME
;
306 eState
= STATE_ERROR
;
310 if (*p
>= '0' && *p
<= '9')
311 nSize
= 10 * nSize
+ (*p
- '0');
312 else if (ascii_isWhitespace(*p
))
313 eState
= STATE_LWS_NAME
;
315 eState
= STATE_ERROR
;
319 if (*p
>= '0' && *p
<= '9')
320 nSize
= 10 * nSize
+ (*p
- '0');
321 else if (ascii_isWhitespace(*p
))
322 eState
= STATE_2_SIZE_LWS
;
324 eState
= STATE_ERROR
;
327 case STATE_2_SIZE_LWS
:
328 if (*p
== 'd' || *p
== 'D')
330 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
331 eState
= STATE_2_ATTRIB
;
332 else if (*p
>= '0' && *p
<= '9')
336 eState
= STATE_2_MONTH
;
338 else if (!ascii_isWhitespace(*p
))
339 eState
= STATE_ERROR
;
343 if (ascii_isWhitespace(*p
))
344 eState
= STATE_2_SIZE_LWS
;
345 else if ((*p
< 'a' || *p
> 'z') && (*p
< 'A' || *p
> 'Z'))
346 eState
= STATE_ERROR
;
350 if (*p
== 'i' || *p
== 'I')
352 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
353 eState
= STATE_2_ATTRIB
;
354 else if (ascii_isWhitespace(*p
))
355 eState
= STATE_2_SIZE_LWS
;
357 eState
= STATE_ERROR
;
361 if (*p
== 'r' || *p
== 'R')
364 eState
= STATE_2_DIR_LWS
;
368 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
369 eState
= STATE_2_ATTRIB
;
370 else if (ascii_isWhitespace(*p
))
371 eState
= STATE_2_SIZE_LWS
;
373 eState
= STATE_ERROR
;
377 case STATE_2_DIR_LWS
:
378 if (*p
>= '0' && *p
<= '9')
382 eState
= STATE_2_MONTH
;
384 else if (!ascii_isWhitespace(*p
))
385 eState
= STATE_ERROR
;
389 if (*p
>= '0' && *p
<= '9')
392 nMonth
= 10 * nMonth
+ (*p
- '0');
396 eState
= STATE_ERROR
;
397 else if (*p
== '-' && nMonth
&& nMonth
<= 12)
400 eState
= STATE_2_DAY
;
403 eState
= STATE_ERROR
;
407 if (*p
>= '0' && *p
<= '9')
410 nDay
= 10 * nDay
+ (*p
- '0');
414 eState
= STATE_ERROR
;
415 else if (*p
== '-' && nDay
&& nDay
<= 31)
418 eState
= STATE_2_YEAR
;
421 eState
= STATE_ERROR
;
425 if (*p
>= '0' && *p
<= '9')
429 nYear
= 10 * nYear
+ (*p
- '0');
433 eState
= STATE_ERROR
;
437 if (ascii_isWhitespace(*p
))
438 eState
= STATE_2_YEAR_LWS
;
440 eState
= STATE_ERROR
;
444 case STATE_2_YEAR_LWS
:
445 if (*p
>= '0' && *p
<= '9')
449 eState
= STATE_2_HOUR
;
451 else if (!ascii_isWhitespace(*p
))
452 eState
= STATE_ERROR
;
456 if (*p
>= '0' && *p
<= '9')
459 nHour
= 10 * nHour
+ (*p
- '0');
463 eState
= STATE_ERROR
;
464 else if (*p
== ':' && nHour
< 24)
467 eState
= STATE_2_MINUTE
;
470 eState
= STATE_ERROR
;
474 if (*p
>= '0' && *p
<= '9')
478 nMinute
= 10 * nMinute
+ (*p
- '0');
482 eState
= STATE_ERROR
;
486 if (ascii_isWhitespace(*p
) && (nMinute
< 60))
487 eState
= STATE_LWS_NAME
;
489 eState
= STATE_ERROR
;
494 if (!ascii_isWhitespace(*p
))
496 setPath (rEntry
.m_aName
, p
);
498 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
499 rEntry
.m_nSize
= nSize
;
501 setYear (rEntry
.m_aDate
, nYear
);
503 rEntry
.m_aDate
.SetMonth(nMonth
);
504 rEntry
.m_aDate
.SetDay(nDay
);
505 rEntry
.m_aDate
.SetHour(nHour
);
506 rEntry
.m_aDate
.SetMin(nMinute
);
521 * Directory entries may span one or two lines:
523 * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest
525 * name: filename "." filetype ";" version
526 * filename: 1*39fchar
527 * filetype: 1*39fchar
528 * version: non0digit *digit
530 * size: "0" / non0digit *digit
532 * datetime: date 1*lwsp time
533 * date: day "-" month "-" year
534 * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1")
535 * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG"
536 * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive
537 * year: 2digit / 4digit
538 * time: hour ":" minute
539 * hour: ((*1"0" / "1") digit) / ("2" "0"-"3")
540 * minute: "0"-"5" digit
542 * rest: *1(lws *<ANY>)
544 * lws: <TAB> / <SPACE>
546 * digit: "0" / non0digit
547 * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$"
549 * For directories, the returned name is the <filename> part; for non-
550 * directory files, the returned name is the <filename "." filetype> part.
551 * An entry is a directory iff its filetype is "DIR" (ignoring case).
553 * The READ, WRITE, and ISLINK mode bits are not supported.
555 * The returned size is the <size> part, multiplied by 512, and with the high
556 * order bits truncated to fit into a ULONG.
559 bool FTPDirectoryParser::parseVMS (
561 const sal_Char
*pBuffer
)
563 static OUString aFirstLineName
;
564 static bool bFirstLineDir
= false;
566 for (bool bFirstLine
= true;; bFirstLine
= false)
568 const sal_Char
*p
= pBuffer
;
572 while (*p
== '\t' || *p
== ' ')
575 // Parse <filename "."> part:
576 const sal_Char
*pFileName
= p
;
577 while ((*p
>= 'A' && *p
<= 'Z') ||
578 (*p
>= 'a' && *p
<= 'z') ||
579 (*p
>= '0' && *p
<= '9') ||
580 *p
== '-' || *p
== '_' || *p
== '$')
583 if (*p
!= '.' || p
== pFileName
|| p
- pFileName
> 39)
585 if (!aFirstLineName
.isEmpty())
591 // Parse <filetype ";"> part:
592 const sal_Char
*pFileType
= ++p
;
593 while ((*p
>= 'A' && *p
<= 'Z') ||
594 (*p
>= 'a' && *p
<= 'z') ||
595 (*p
>= '0' && *p
<= '9') ||
596 *p
== '-' || *p
== '_' || *p
== '$')
599 if (*p
!= ';' || p
== pFileName
|| p
- pFileName
> 39)
601 if (!aFirstLineName
.isEmpty())
608 // Set entry's name and mode (ISDIR flag):
609 if ((p
- pFileType
== 4) &&
610 (pFileType
[0] == 'D' || pFileType
[0] == 'd') &&
611 (pFileType
[1] == 'I' || pFileType
[1] == 'i') &&
612 (pFileType
[2] == 'R' || pFileType
[2] == 'r') )
614 setPath (rEntry
.m_aName
, pFileName
, (pFileType
- pFileName
));
615 rEntry
.m_nMode
= INETCOREFTP_FILEMODE_ISDIR
;
619 setPath (rEntry
.m_aName
, pFileName
, (p
- pFileName
));
623 // Skip <version> part:
624 if (*p
< '1' || *p
> '9')
626 if (!aFirstLineName
.isEmpty())
632 while (*p
>= '0' && *p
<= '9')
635 // Parse <1*lws> or <*lws <NEWLINE>> part:
637 while (*p
== '\t' || *p
== ' ')
646 if (!aFirstLineName
.isEmpty())
655 * First line of entry spanning two lines,
656 * wait for second line.
658 aFirstLineName
= rEntry
.m_aName
;
660 ((rEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
) != 0);
667 * Second line of entry spanning two lines,
668 * restore entry's name and mode (ISDIR flag).
670 rEntry
.m_aName
= aFirstLineName
;
671 rEntry
.m_nMode
= (bFirstLineDir
? INETCOREFTP_FILEMODE_ISDIR
: 0);
673 // Skip <1*lws> part:
674 if (*p
!= '\t' && *p
!= ' ')
677 while (*p
== '\t' || *p
== ' ')
681 // Parse <size> part and set entry's size:
682 if (*p
< '0' || *p
> '9')
684 ULONG nSize
= *p
- '0';
686 while (*p
>= '0' && *p
<= '9')
687 nSize
= 10 * rEntry
.m_nSize
+ (*p
++ - '0');
688 rEntry
.m_nSize
= 512 * nSize
;
690 // Skip <1*lws> part:
691 if (*p
!= '\t' && *p
!= ' ')
694 while (*p
== '\t' || *p
== ' ')
697 // Parse <day "-"> part and set entry date's day:
702 if (*p
< '1' || *p
> '9')
706 else if (*p
== '1' || *p
== '2')
709 if (*p
>= '0' && *p
<= '9')
710 nDay
= 10 * nDay
+ (*p
++ - '0');
715 nDay
= (*p
== '0' || *p
== '1') ? 30 + (*p
++ - '0') : 3;
717 else if (*p
>= '4' && *p
<= '9')
722 rEntry
.m_aDate
.SetDay(nDay
);
726 // Parse <month "-"> part and set entry date's month:
727 sal_Char
const * pMonth
= p
;
728 sal_Int32
const monthLen
= 3;
729 for (int i
= 0; i
< monthLen
; ++i
)
731 if (!((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z')))
735 if (rtl_str_compareIgnoreAsciiCase_WithLength(
736 pMonth
, monthLen
, "JAN", monthLen
) == 0)
737 rEntry
.m_aDate
.SetMonth(1);
738 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
739 pMonth
, monthLen
, "FEB", monthLen
) == 0)
740 rEntry
.m_aDate
.SetMonth(2);
741 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
742 pMonth
, monthLen
, "MAR", monthLen
) == 0)
743 rEntry
.m_aDate
.SetMonth(3);
744 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
745 pMonth
, monthLen
, "APR", monthLen
) == 0)
746 rEntry
.m_aDate
.SetMonth(4);
747 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
748 pMonth
, monthLen
, "MAY", monthLen
) == 0)
749 rEntry
.m_aDate
.SetMonth(5);
750 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
751 pMonth
, monthLen
, "JUN", monthLen
) == 0)
752 rEntry
.m_aDate
.SetMonth(6);
753 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
754 pMonth
, monthLen
, "JUL", monthLen
) == 0)
755 rEntry
.m_aDate
.SetMonth(7);
756 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
757 pMonth
, monthLen
, "AUG", monthLen
) == 0)
758 rEntry
.m_aDate
.SetMonth(8);
759 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
760 pMonth
, monthLen
, "SEP", monthLen
) == 0)
761 rEntry
.m_aDate
.SetMonth(9);
762 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
763 pMonth
, monthLen
, "OCT", monthLen
) == 0)
764 rEntry
.m_aDate
.SetMonth(10);
765 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
766 pMonth
, monthLen
, "NOV", monthLen
) == 0)
767 rEntry
.m_aDate
.SetMonth(11);
768 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
769 pMonth
, monthLen
, "DEC", monthLen
) == 0)
770 rEntry
.m_aDate
.SetMonth(12);
776 // Parse <year> part and set entry date's year:
777 sal_uInt16 nYear
= 0;
778 for (int i
= 0; i
< 2; ++i
)
780 if (*p
< '0' || *p
> '9')
782 nYear
= 10 * nYear
+ (*p
++ - '0');
784 if (*p
>= '0' && *p
<= '9')
786 nYear
= 10 * nYear
+ (*p
++ - '0');
787 if (*p
< '0' || *p
> '9')
789 nYear
= 10 * nYear
+ (*p
++ - '0');
791 setYear (rEntry
.m_aDate
, nYear
);
793 // Skip <1*lws> part:
794 if (*p
!= '\t' && *p
!= ' ')
797 while (*p
== '\t' || *p
== ' ')
800 // Parse <hour ":"> part and set entry time's hour:
802 if (*p
== '0' || *p
== '1')
805 if (*p
>= '0' && *p
<= '9')
806 nHour
= 10 * nHour
+ (*p
++ - '0');
811 nHour
= (*p
>= '0' && *p
<= '3') ? 20 + (*p
++ - '0') : 2;
813 else if (*p
>= '3' && *p
<= '9')
818 rEntry
.m_aDate
.SetHour(nHour
);
823 * Parse <minute> part and set entry time's minutes,
824 * seconds (0), and nanoseconds (0).
826 if (*p
< '0' || *p
> '5')
829 sal_uInt16 nMinute
= *p
++ - '0';
830 if (*p
< '0' || *p
> '9')
833 nMinute
= 10 * nMinute
+ (*p
++ - '0');
834 rEntry
.m_aDate
.SetMin(nMinute
);
835 rEntry
.m_aDate
.SetSec(0);
836 rEntry
.m_aDate
.SetNanoSec(0);
839 if (*p
&& (*p
!= '\t' && *p
!= ' '))
849 bool FTPDirectoryParser::parseUNIX (
851 const sal_Char
*pBuffer
)
853 const sal_Char
*p1
, *p2
;
856 if (!((*p1
== '-') || (*p1
== 'd') || (*p1
== 'l')))
859 // 1st column: FileMode.
861 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
864 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISLINK
;
866 // Skip to end of column and set rights by the way
867 while (*p1
&& !ascii_isWhitespace(*p1
)) {
869 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_READ
;
871 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_WRITE
;
876 * Scan for the sequence of size and date fields:
877 * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS
878 * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS
882 FOUND_NONE
, FOUND_SIZE
, FOUND_MONTH
, FOUND_DAY
, FOUND_YEAR_TIME
885 const sal_Char
*pDayStart
= 0;
886 const sal_Char
*pDayEnd
= 0;
888 for (eMode
= FOUND_NONE
; *p1
&& eMode
!= FOUND_YEAR_TIME
; p1
= p2
+ 1)
890 while (*p1
&& ascii_isWhitespace(*p1
))
893 while (*p2
&& !ascii_isWhitespace(*p2
))
899 if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
904 if (parseUNIX_isMonthField (p1
, p2
, rEntry
.m_aDate
))
906 else if (!parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
911 if (parseUNIX_isDayField (p1
, p2
, rEntry
.m_aDate
))
917 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
924 if (parseUNIX_isYearTimeField (p1
, p2
, rEntry
.m_aDate
))
925 eMode
= FOUND_YEAR_TIME
;
927 parseUNIX_isSizeField (
928 pDayStart
, pDayEnd
, rEntry
.m_nSize
) &&
929 parseUNIX_isMonthField (
930 p1
, p2
, rEntry
.m_aDate
))
932 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
937 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
938 case FOUND_YEAR_TIME
:
943 if (eMode
== FOUND_YEAR_TIME
)
945 // 9th column: FileName (rest of line).
946 while (*p1
&& ascii_isWhitespace(*p1
)) p1
++;
947 setPath (rEntry
.m_aName
, p1
);
956 * parseUNIX_isSizeField.
958 bool FTPDirectoryParser::parseUNIX_isSizeField (
959 const sal_Char
*pStart
,
960 const sal_Char
*pEnd
,
963 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
967 if (*pStart
>= '0' && *pStart
<= '9')
969 for (; pStart
< pEnd
; ++pStart
)
970 if ((*pStart
>= '0') && (*pStart
<= '9'))
971 rSize
= 10 * rSize
+ (*pStart
- '0');
979 * For a combination of long group name and large file size,
980 * some FTPDs omit LWS between those two columns.
985 for (; pStart
< pEnd
; ++pStart
)
986 if ((*pStart
>= '1') && (*pStart
<= '9'))
989 rSize
= 10 * rSize
+ (*pStart
- '0');
991 else if ((*pStart
== '0') && nDigits
)
996 else if ((*pStart
> ' ') && (sal::static_int_cast
<sal_uInt8
>(*pStart
) <= '\x7F'))
998 nNonDigits
+= nDigits
+ 1;
1004 return ((nNonDigits
>= 9) && (nDigits
>= 7));
1009 * parseUNIX_isMonthField.
1011 bool FTPDirectoryParser::parseUNIX_isMonthField (
1012 const sal_Char
*pStart
,
1013 const sal_Char
*pEnd
,
1014 DateTime
&rDateTime
)
1016 if (!*pStart
|| !*pEnd
|| pStart
+ 3 != pEnd
)
1019 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1020 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1021 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1023 rDateTime
.SetMonth(1);
1026 if ((pStart
[0] == 'f' || pStart
[0] == 'F') &&
1027 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1028 (pStart
[2] == 'b' || pStart
[2] == 'B') )
1030 rDateTime
.SetMonth(2);
1033 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1034 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1035 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1037 rDateTime
.SetMonth(3);
1040 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1041 (pStart
[1] == 'p' || pStart
[1] == 'P') &&
1042 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1044 rDateTime
.SetMonth(4);
1047 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1048 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1049 (pStart
[2] == 'y' || pStart
[2] == 'Y') )
1051 rDateTime
.SetMonth(5);
1054 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1055 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1056 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1058 rDateTime
.SetMonth(6);
1061 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1062 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1063 (pStart
[2] == 'l' || pStart
[2] == 'L') )
1065 rDateTime
.SetMonth(7);
1068 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1069 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1070 (pStart
[2] == 'g' || pStart
[2] == 'G') )
1072 rDateTime
.SetMonth(8);
1075 if ((pStart
[0] == 's' || pStart
[0] == 'S') &&
1076 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1077 (pStart
[2] == 'p' || pStart
[2] == 'P') )
1079 rDateTime
.SetMonth(9);
1082 if ((pStart
[0] == 'o' || pStart
[0] == 'O') &&
1083 (pStart
[1] == 'c' || pStart
[1] == 'C') &&
1084 (pStart
[2] == 't' || pStart
[2] == 'T') )
1086 rDateTime
.SetMonth(10);
1089 if ((pStart
[0] == 'n' || pStart
[0] == 'N') &&
1090 (pStart
[1] == 'o' || pStart
[1] == 'O') &&
1091 (pStart
[2] == 'v' || pStart
[2] == 'V') )
1093 rDateTime
.SetMonth(11);
1096 if ((pStart
[0] == 'd' || pStart
[0] == 'D') &&
1097 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1098 (pStart
[2] == 'c' || pStart
[2] == 'C') )
1100 rDateTime
.SetMonth(12);
1107 * parseUNIX_isDayField.
1109 bool FTPDirectoryParser::parseUNIX_isDayField (
1110 const sal_Char
*pStart
,
1111 const sal_Char
*pEnd
,
1112 DateTime
&rDateTime
)
1114 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1116 if (*pStart
< '0' || *pStart
> '9')
1119 sal_uInt16 nDay
= *pStart
- '0';
1120 if (pStart
+ 1 < pEnd
)
1122 if (pStart
+ 2 != pEnd
|| pStart
[1] < '0' || pStart
[1] > '9')
1124 nDay
= 10 * nDay
+ (pStart
[1] - '0');
1126 if (!nDay
|| nDay
> 31)
1129 rDateTime
.SetDay(nDay
);
1134 * parseUNIX_isYearTimeField.
1136 bool FTPDirectoryParser::parseUNIX_isYearTimeField (
1137 const sal_Char
*pStart
,
1138 const sal_Char
*pEnd
,
1139 DateTime
&rDateTime
)
1141 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
||
1142 *pStart
< '0' || *pStart
> '9')
1145 sal_uInt16 nNumber
= *pStart
- '0';
1151 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1152 if (*pStart
< '0' || *pStart
> '9')
1155 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1161 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1162 if (*pStart
< '0' || *pStart
> '9')
1165 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1168 if (pStart
== pEnd
|| *pStart
< '0' || *pStart
> '9')
1171 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1172 if (pStart
+ 1 != pEnd
|| nNumber
< 1970)
1175 rDateTime
.SetYear(nNumber
);
1176 rDateTime
.SetTime(0);
1183 bool FTPDirectoryParser::parseUNIX_isTime (
1184 const sal_Char
*pStart
,
1185 const sal_Char
*pEnd
,
1187 DateTime
&rDateTime
)
1189 if ((nHour
> 23 ) || (pStart
+ 3 != pEnd
) ||
1190 (pStart
[1] < '0') || (pStart
[1] > '5') ||
1191 (pStart
[2] < '0') || (pStart
[2] > '9') )
1194 sal_uInt16 nMin
= 10 * (pStart
[1] - '0') + (pStart
[2] - '0');
1196 rDateTime
.SetHour (nHour
);
1197 rDateTime
.SetMin (nMin
);
1198 rDateTime
.SetSec (0);
1199 rDateTime
.SetNanoSec (0);
1202 // if (rDateTime.GetMonth() > aCurDate.GetMonth())
1203 // rDateTime.SetYear(aCurDate.GetYear() - 1);
1205 // rDateTime.SetYear(aCurDate.GetYear());
1209 osl_getSystemTime(&aTimeVal
);
1210 oslDateTime aCurrDateTime
;
1211 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1213 if (rDateTime
.GetMonth() > aCurrDateTime
.Month
)
1214 rDateTime
.SetYear(aCurrDateTime
.Year
- 1);
1216 rDateTime
.SetYear(aCurrDateTime
.Year
);
1223 * Two-digit years are taken as within 50 years back and 49 years forward
1224 * (both ends inclusive) from the current year. The returned date is not
1225 * checked for validity of the given day in the given month and year.
1228 bool FTPDirectoryParser::setYear (
1229 DateTime
&rDateTime
, sal_uInt16 nYear
)
1234 osl_getSystemTime(&aTimeVal
);
1235 oslDateTime aCurrDateTime
;
1236 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1237 sal_uInt16 nCurrentYear
= aCurrDateTime
.Year
;
1238 // sal_uInt16 nCurrentYear = Date().GetYear();
1239 sal_uInt16 nCurrentCentury
= nCurrentYear
/ 100;
1240 nCurrentYear
%= 100;
1241 if (nCurrentYear
< 50)
1242 if (nYear
<= nCurrentYear
)
1243 nYear
+= nCurrentCentury
* 100;
1244 else if (nYear
< nCurrentYear
+ 50)
1245 nYear
+= nCurrentCentury
* 100;
1247 nYear
+= (nCurrentCentury
- 1) * 100;
1249 if (nYear
>= nCurrentYear
)
1250 nYear
+= nCurrentCentury
* 100;
1251 else if (nYear
>= nCurrentYear
- 50)
1252 nYear
+= nCurrentCentury
* 100;
1254 nYear
+= (nCurrentCentury
+ 1) * 100;
1257 rDateTime
.SetYear(nYear
);
1264 bool FTPDirectoryParser::setPath (
1265 OUString
&rPath
, const sal_Char
*value
, sal_Int32 length
)
1270 length
= rtl_str_getLength (value
);
1271 rPath
= OUString (value
, length
, RTL_TEXTENCODING_UTF8
);
1276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */