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 static bool ascii_isWhitespace( sal_Unicode ch
)
34 return ((ch
<= 0x20) && ch
);
38 /*========================================================================
40 * FTPDirectoryParser implementation.
42 *======================================================================*/
45 * Accepts one of two styles:
47 * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP
48 * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP
49 * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET
51 * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name
53 * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT
54 * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET
56 * interpreted as: size attribs DIR mm-dd-yy hh:mm name
59 bool FTPDirectoryParser::parseDOS (
63 bool bDirectory
= false;
66 sal_uInt16 nMonth
= 0;
69 sal_uInt16 nMinute
= 0;
75 STATE_1_DAY
, STATE_1_YEAR
, STATE_1_YEAR_LWS
, STATE_1_HOUR
,
76 STATE_1_MINUTE
, STATE_1_MINUTE_LWS
, STATE_1_AP
,
77 STATE_1_APM
, STATE_1_LESS
, STATE_1_D
, STATE_1_DI
,
78 STATE_1_DIR
, STATE_1_SIZE
,
79 STATE_2_SIZE
, STATE_2_SIZE_LWS
, STATE_2_ATTRIB
,
80 STATE_2_D
, STATE_2_DI
, STATE_2_DIR_LWS
,
81 STATE_2_MONTH
, STATE_2_DAY
, STATE_2_YEAR
, STATE_2_YEAR_LWS
,
82 STATE_2_HOUR
, STATE_2_MINUTE
,
88 enum StateType eState
= STATE_INIT_LWS
;
89 for (const char *p
= pBuffer
;
90 eState
!= STATE_ERROR
&& *p
;
96 if (*p
>= '0' && *p
<= '9')
100 eState
= STATE_MONTH_OR_SIZE
;
102 else if (!ascii_isWhitespace(*p
))
103 eState
= STATE_ERROR
;
106 case STATE_MONTH_OR_SIZE
:
107 if (*p
>= '0' && *p
<= '9')
109 nMonth
= 10 * nMonth
+ (*p
- '0');
116 eState
= STATE_2_SIZE
;
119 else if (ascii_isWhitespace(*p
))
123 eState
= STATE_2_SIZE_LWS
;
125 else if ((*p
== '.' || *p
== '-') && nMonth
&& nMonth
<= 12)
128 eState
= STATE_1_DAY
;
131 eState
= STATE_ERROR
;
135 if (*p
>= '0' && *p
<= '9')
138 nDay
= 10 * nDay
+ (*p
- '0');
142 eState
= STATE_ERROR
;
143 else if ((*p
== '.' || *p
== '-') && nDay
&& nDay
<= 31)
146 eState
= STATE_1_YEAR
;
149 eState
= STATE_ERROR
;
153 if (*p
>= '0' && *p
<= '9')
157 nYear
= 10 * nYear
+ (*p
- '0');
161 eState
= STATE_ERROR
;
165 if (ascii_isWhitespace(*p
))
166 eState
= STATE_1_YEAR_LWS
;
168 eState
= STATE_ERROR
;
172 case STATE_1_YEAR_LWS
:
173 if (*p
>= '0' && *p
<= '9')
177 eState
= STATE_1_HOUR
;
179 else if (!ascii_isWhitespace(*p
))
180 eState
= STATE_ERROR
;
184 if (*p
>= '0' && *p
<= '9')
187 nHour
= 10 * nHour
+ (*p
- '0');
191 eState
= STATE_ERROR
;
192 else if (*p
== ':' && nHour
< 24)
195 eState
= STATE_1_MINUTE
;
198 eState
= STATE_ERROR
;
202 if (*p
>= '0' && *p
<= '9')
205 nMinute
= 10 * nMinute
+ (*p
- '0');
209 eState
= STATE_ERROR
;
210 else if ((*p
== 'a' || *p
== 'A') && nMinute
< 60)
211 if (nHour
>= 1 && nHour
<= 11)
213 else if (nHour
== 12)
219 eState
= STATE_ERROR
;
220 else if ((*p
== 'p' || *p
== 'P') && nMinute
< 60)
221 if (nHour
>= 1 && nHour
<= 11)
226 else if (nHour
== 12)
229 eState
= STATE_ERROR
;
230 else if (ascii_isWhitespace(*p
) && (nMinute
< 60))
231 eState
= STATE_1_MINUTE_LWS
;
233 eState
= STATE_ERROR
;
236 case STATE_1_MINUTE_LWS
:
237 if (*p
== 'a' || *p
== 'A')
238 if (nHour
>= 1 && nHour
<= 11)
240 else if (nHour
== 12)
246 eState
= STATE_ERROR
;
247 else if (*p
== 'p' || *p
== 'P')
248 if (nHour
>= 1 && nHour
<= 11)
253 else if (nHour
== 12)
256 eState
= STATE_ERROR
;
258 eState
= STATE_1_LESS
;
259 else if (*p
>= '0' && *p
<= '9')
262 eState
= STATE_1_SIZE
;
264 else if (!ascii_isWhitespace(*p
))
265 eState
= STATE_ERROR
;
269 eState
= *p
== 'm' || *p
== 'M' ? STATE_1_APM
: STATE_ERROR
;
274 eState
= STATE_1_LESS
;
275 else if (*p
>= '0' && *p
<= '9')
278 eState
= STATE_1_SIZE
;
280 else if (!ascii_isWhitespace(*p
))
281 eState
= STATE_ERROR
;
285 eState
= *p
== 'd' || *p
== 'D' ? STATE_1_D
: STATE_ERROR
;
289 eState
= *p
== 'i' || *p
== 'I' ? STATE_1_DI
: STATE_ERROR
;
293 eState
= *p
== 'r' || *p
== 'R' ? STATE_1_DIR
: STATE_ERROR
;
300 eState
= STATE_LWS_NAME
;
303 eState
= STATE_ERROR
;
307 if (*p
>= '0' && *p
<= '9')
308 nSize
= 10 * nSize
+ (*p
- '0');
309 else if (ascii_isWhitespace(*p
))
310 eState
= STATE_LWS_NAME
;
312 eState
= STATE_ERROR
;
316 if (*p
>= '0' && *p
<= '9')
317 nSize
= 10 * nSize
+ (*p
- '0');
318 else if (ascii_isWhitespace(*p
))
319 eState
= STATE_2_SIZE_LWS
;
321 eState
= STATE_ERROR
;
324 case STATE_2_SIZE_LWS
:
325 if (*p
== 'd' || *p
== 'D')
327 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
328 eState
= STATE_2_ATTRIB
;
329 else if (*p
>= '0' && *p
<= '9')
333 eState
= STATE_2_MONTH
;
335 else if (!ascii_isWhitespace(*p
))
336 eState
= STATE_ERROR
;
340 if (ascii_isWhitespace(*p
))
341 eState
= STATE_2_SIZE_LWS
;
342 else if ((*p
< 'a' || *p
> 'z') && (*p
< 'A' || *p
> 'Z'))
343 eState
= STATE_ERROR
;
347 if (*p
== 'i' || *p
== 'I')
349 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
350 eState
= STATE_2_ATTRIB
;
351 else if (ascii_isWhitespace(*p
))
352 eState
= STATE_2_SIZE_LWS
;
354 eState
= STATE_ERROR
;
358 if (*p
== 'r' || *p
== 'R')
361 eState
= STATE_2_DIR_LWS
;
365 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
366 eState
= STATE_2_ATTRIB
;
367 else if (ascii_isWhitespace(*p
))
368 eState
= STATE_2_SIZE_LWS
;
370 eState
= STATE_ERROR
;
374 case STATE_2_DIR_LWS
:
375 if (*p
>= '0' && *p
<= '9')
379 eState
= STATE_2_MONTH
;
381 else if (!ascii_isWhitespace(*p
))
382 eState
= STATE_ERROR
;
386 if (*p
>= '0' && *p
<= '9')
389 nMonth
= 10 * nMonth
+ (*p
- '0');
393 eState
= STATE_ERROR
;
394 else if (*p
== '-' && nMonth
&& nMonth
<= 12)
397 eState
= STATE_2_DAY
;
400 eState
= STATE_ERROR
;
404 if (*p
>= '0' && *p
<= '9')
407 nDay
= 10 * nDay
+ (*p
- '0');
411 eState
= STATE_ERROR
;
412 else if (*p
== '-' && nDay
&& nDay
<= 31)
415 eState
= STATE_2_YEAR
;
418 eState
= STATE_ERROR
;
422 if (*p
>= '0' && *p
<= '9')
426 nYear
= 10 * nYear
+ (*p
- '0');
430 eState
= STATE_ERROR
;
434 if (ascii_isWhitespace(*p
))
435 eState
= STATE_2_YEAR_LWS
;
437 eState
= STATE_ERROR
;
441 case STATE_2_YEAR_LWS
:
442 if (*p
>= '0' && *p
<= '9')
446 eState
= STATE_2_HOUR
;
448 else if (!ascii_isWhitespace(*p
))
449 eState
= STATE_ERROR
;
453 if (*p
>= '0' && *p
<= '9')
456 nHour
= 10 * nHour
+ (*p
- '0');
460 eState
= STATE_ERROR
;
461 else if (*p
== ':' && nHour
< 24)
464 eState
= STATE_2_MINUTE
;
467 eState
= STATE_ERROR
;
471 if (*p
>= '0' && *p
<= '9')
475 nMinute
= 10 * nMinute
+ (*p
- '0');
479 eState
= STATE_ERROR
;
483 if (ascii_isWhitespace(*p
) && (nMinute
< 60))
484 eState
= STATE_LWS_NAME
;
486 eState
= STATE_ERROR
;
491 if (!ascii_isWhitespace(*p
))
493 setPath (rEntry
.m_aName
, p
);
495 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
496 rEntry
.m_nSize
= nSize
;
498 setYear (rEntry
.m_aDate
, nYear
);
500 rEntry
.m_aDate
.SetMonth(nMonth
);
501 rEntry
.m_aDate
.SetDay(nDay
);
502 rEntry
.m_aDate
.SetHour(nHour
);
503 rEntry
.m_aDate
.SetMin(nMinute
);
518 * Directory entries may span one or two lines:
520 * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest
522 * name: filename "." filetype ";" version
523 * filename: 1*39fchar
524 * filetype: 1*39fchar
525 * version: non0digit *digit
527 * size: "0" / non0digit *digit
529 * datetime: date 1*lwsp time
530 * date: day "-" month "-" year
531 * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1")
532 * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG"
533 * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive
534 * year: 2digit / 4digit
535 * time: hour ":" minute
536 * hour: ((*1"0" / "1") digit) / ("2" "0"-"3")
537 * minute: "0"-"5" digit
539 * rest: *1(lws *<ANY>)
541 * lws: <TAB> / <SPACE>
543 * digit: "0" / non0digit
544 * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$"
546 * For directories, the returned name is the <filename> part; for non-
547 * directory files, the returned name is the <filename "." filetype> part.
548 * An entry is a directory iff its filetype is "DIR" (ignoring case).
550 * The READ, WRITE, and ISLINK mode bits are not supported.
552 * The returned size is the <size> part, multiplied by 512, and with the high
553 * order bits truncated to fit into a sal_uInt32.
556 bool FTPDirectoryParser::parseVMS (
560 static OUString aFirstLineName
;
561 static bool bFirstLineDir
= false;
563 for (bool bFirstLine
= true;; bFirstLine
= false)
565 const char *p
= pBuffer
;
569 while (*p
== '\t' || *p
== ' ')
572 // Parse <filename "."> part:
573 const char *pFileName
= p
;
574 while ((*p
>= 'A' && *p
<= 'Z') ||
575 (*p
>= 'a' && *p
<= 'z') ||
576 (*p
>= '0' && *p
<= '9') ||
577 *p
== '-' || *p
== '_' || *p
== '$')
580 if (*p
!= '.' || p
== pFileName
|| p
- pFileName
> 39)
582 if (!aFirstLineName
.isEmpty())
588 // Parse <filetype ";"> part:
589 const char *pFileType
= ++p
;
590 while ((*p
>= 'A' && *p
<= 'Z') ||
591 (*p
>= 'a' && *p
<= 'z') ||
592 (*p
>= '0' && *p
<= '9') ||
593 *p
== '-' || *p
== '_' || *p
== '$')
596 if (*p
!= ';' || p
== pFileName
|| p
- pFileName
> 39)
598 if (!aFirstLineName
.isEmpty())
605 // Set entry's name and mode (ISDIR flag):
606 if ((p
- pFileType
== 4) &&
607 (pFileType
[0] == 'D' || pFileType
[0] == 'd') &&
608 (pFileType
[1] == 'I' || pFileType
[1] == 'i') &&
609 (pFileType
[2] == 'R' || pFileType
[2] == 'r') )
611 setPath (rEntry
.m_aName
, pFileName
, (pFileType
- pFileName
));
612 rEntry
.m_nMode
= INETCOREFTP_FILEMODE_ISDIR
;
616 setPath (rEntry
.m_aName
, pFileName
, (p
- pFileName
));
620 // Skip <version> part:
621 if (*p
< '1' || *p
> '9')
623 if (!aFirstLineName
.isEmpty())
629 while (*p
>= '0' && *p
<= '9')
632 // Parse <1*lws> or <*lws <NEWLINE>> part:
634 while (*p
== '\t' || *p
== ' ')
643 if (!aFirstLineName
.isEmpty())
652 * First line of entry spanning two lines,
653 * wait for second line.
655 aFirstLineName
= rEntry
.m_aName
;
657 ((rEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
) != 0);
664 * Second line of entry spanning two lines,
665 * restore entry's name and mode (ISDIR flag).
667 rEntry
.m_aName
= aFirstLineName
;
668 rEntry
.m_nMode
= (bFirstLineDir
? INETCOREFTP_FILEMODE_ISDIR
: 0);
670 // Skip <1*lws> part:
671 if (*p
!= '\t' && *p
!= ' ')
674 while (*p
== '\t' || *p
== ' ')
678 // Parse <size> part and set entry's size:
679 if (*p
< '0' || *p
> '9')
681 sal_uInt32 nSize
= *p
- '0';
683 while (*p
>= '0' && *p
<= '9')
684 nSize
= 10 * rEntry
.m_nSize
+ (*p
++ - '0');
685 rEntry
.m_nSize
= 512 * nSize
;
687 // Skip <1*lws> part:
688 if (*p
!= '\t' && *p
!= ' ')
691 while (*p
== '\t' || *p
== ' ')
694 // Parse <day "-"> part and set entry date's day:
699 if (*p
< '1' || *p
> '9')
703 else if (*p
== '1' || *p
== '2')
706 if (*p
>= '0' && *p
<= '9')
707 nDay
= 10 * nDay
+ (*p
++ - '0');
712 nDay
= (*p
== '0' || *p
== '1') ? 30 + (*p
++ - '0') : 3;
714 else if (*p
>= '4' && *p
<= '9')
719 rEntry
.m_aDate
.SetDay(nDay
);
723 // Parse <month "-"> part and set entry date's month:
724 char const * pMonth
= p
;
725 sal_Int32
const monthLen
= 3;
726 for (int i
= 0; i
< monthLen
; ++i
)
728 if (!((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z')))
732 if (rtl_str_compareIgnoreAsciiCase_WithLength(
733 pMonth
, monthLen
, "JAN", monthLen
) == 0)
734 rEntry
.m_aDate
.SetMonth(1);
735 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
736 pMonth
, monthLen
, "FEB", monthLen
) == 0)
737 rEntry
.m_aDate
.SetMonth(2);
738 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
739 pMonth
, monthLen
, "MAR", monthLen
) == 0)
740 rEntry
.m_aDate
.SetMonth(3);
741 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
742 pMonth
, monthLen
, "APR", monthLen
) == 0)
743 rEntry
.m_aDate
.SetMonth(4);
744 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
745 pMonth
, monthLen
, "MAY", monthLen
) == 0)
746 rEntry
.m_aDate
.SetMonth(5);
747 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
748 pMonth
, monthLen
, "JUN", monthLen
) == 0)
749 rEntry
.m_aDate
.SetMonth(6);
750 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
751 pMonth
, monthLen
, "JUL", monthLen
) == 0)
752 rEntry
.m_aDate
.SetMonth(7);
753 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
754 pMonth
, monthLen
, "AUG", monthLen
) == 0)
755 rEntry
.m_aDate
.SetMonth(8);
756 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
757 pMonth
, monthLen
, "SEP", monthLen
) == 0)
758 rEntry
.m_aDate
.SetMonth(9);
759 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
760 pMonth
, monthLen
, "OCT", monthLen
) == 0)
761 rEntry
.m_aDate
.SetMonth(10);
762 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
763 pMonth
, monthLen
, "NOV", monthLen
) == 0)
764 rEntry
.m_aDate
.SetMonth(11);
765 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
766 pMonth
, monthLen
, "DEC", monthLen
) == 0)
767 rEntry
.m_aDate
.SetMonth(12);
773 // Parse <year> part and set entry date's year:
774 sal_uInt16 nYear
= 0;
775 for (int i
= 0; i
< 2; ++i
)
777 if (*p
< '0' || *p
> '9')
779 nYear
= 10 * nYear
+ (*p
++ - '0');
781 if (*p
>= '0' && *p
<= '9')
783 nYear
= 10 * nYear
+ (*p
++ - '0');
784 if (*p
< '0' || *p
> '9')
786 nYear
= 10 * nYear
+ (*p
++ - '0');
788 setYear (rEntry
.m_aDate
, nYear
);
790 // Skip <1*lws> part:
791 if (*p
!= '\t' && *p
!= ' ')
794 while (*p
== '\t' || *p
== ' ')
797 // Parse <hour ":"> part and set entry time's hour:
799 if (*p
== '0' || *p
== '1')
802 if (*p
>= '0' && *p
<= '9')
803 nHour
= 10 * nHour
+ (*p
++ - '0');
808 nHour
= (*p
>= '0' && *p
<= '3') ? 20 + (*p
++ - '0') : 2;
810 else if (*p
>= '3' && *p
<= '9')
815 rEntry
.m_aDate
.SetHour(nHour
);
820 * Parse <minute> part and set entry time's minutes,
821 * seconds (0), and nanoseconds (0).
823 if (*p
< '0' || *p
> '5')
826 sal_uInt16 nMinute
= *p
++ - '0';
827 if (*p
< '0' || *p
> '9')
830 nMinute
= 10 * nMinute
+ (*p
++ - '0');
831 rEntry
.m_aDate
.SetMin(nMinute
);
832 rEntry
.m_aDate
.SetSec(0);
833 rEntry
.m_aDate
.SetNanoSec(0);
836 return !*p
|| *p
== '\t' || *p
== ' ';
843 bool FTPDirectoryParser::parseUNIX (
850 if (!((*p1
== '-') || (*p1
== 'd') || (*p1
== 'l')))
853 // 1st column: FileMode.
855 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
858 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISLINK
;
860 // Skip to end of column and set rights by the way
861 while (*p1
&& !ascii_isWhitespace(*p1
)) {
863 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_READ
;
865 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_WRITE
;
870 * Scan for the sequence of size and date fields:
871 * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS
872 * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS
876 FOUND_NONE
, FOUND_SIZE
, FOUND_MONTH
, FOUND_DAY
, FOUND_YEAR_TIME
879 const char *pDayStart
= nullptr;
880 const char *pDayEnd
= nullptr;
882 for (eMode
= FOUND_NONE
; *p1
&& eMode
!= FOUND_YEAR_TIME
; p1
= p2
+ 1)
884 while (*p1
&& ascii_isWhitespace(*p1
))
887 while (*p2
&& !ascii_isWhitespace(*p2
))
893 if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
898 if (parseUNIX_isMonthField (p1
, p2
, rEntry
.m_aDate
))
900 else if (!parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
905 if (parseUNIX_isDayField (p1
, p2
, rEntry
.m_aDate
))
911 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
918 if (parseUNIX_isYearTimeField (p1
, p2
, rEntry
.m_aDate
))
919 eMode
= FOUND_YEAR_TIME
;
921 parseUNIX_isSizeField (
922 pDayStart
, pDayEnd
, rEntry
.m_nSize
) &&
923 parseUNIX_isMonthField (
924 p1
, p2
, rEntry
.m_aDate
))
926 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
931 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
932 case FOUND_YEAR_TIME
:
937 if (eMode
== FOUND_YEAR_TIME
)
939 // 9th column: FileName (rest of line).
940 while (*p1
&& ascii_isWhitespace(*p1
)) p1
++;
941 setPath (rEntry
.m_aName
, p1
);
950 * parseUNIX_isSizeField.
952 bool FTPDirectoryParser::parseUNIX_isSizeField (
957 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
961 if (*pStart
>= '0' && *pStart
<= '9')
963 for (; pStart
< pEnd
; ++pStart
)
964 if ((*pStart
>= '0') && (*pStart
<= '9'))
965 rSize
= 10 * rSize
+ (*pStart
- '0');
973 * For a combination of long group name and large file size,
974 * some FTPDs omit LWS between those two columns.
979 for (; pStart
< pEnd
; ++pStart
)
980 if ((*pStart
>= '1') && (*pStart
<= '9'))
983 rSize
= 10 * rSize
+ (*pStart
- '0');
985 else if ((*pStart
== '0') && nDigits
)
990 else if ((*pStart
> ' ') && (sal::static_int_cast
<sal_uInt8
>(*pStart
) <= '\x7F'))
992 nNonDigits
+= nDigits
+ 1;
998 return ((nNonDigits
>= 9) && (nDigits
>= 7));
1003 * parseUNIX_isMonthField.
1005 bool FTPDirectoryParser::parseUNIX_isMonthField (
1008 DateTime
&rDateTime
)
1010 if (!*pStart
|| !*pEnd
|| pStart
+ 3 != pEnd
)
1013 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1014 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1015 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1017 rDateTime
.SetMonth(1);
1020 if ((pStart
[0] == 'f' || pStart
[0] == 'F') &&
1021 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1022 (pStart
[2] == 'b' || pStart
[2] == 'B') )
1024 rDateTime
.SetMonth(2);
1027 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1028 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1029 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1031 rDateTime
.SetMonth(3);
1034 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1035 (pStart
[1] == 'p' || pStart
[1] == 'P') &&
1036 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1038 rDateTime
.SetMonth(4);
1041 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1042 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1043 (pStart
[2] == 'y' || pStart
[2] == 'Y') )
1045 rDateTime
.SetMonth(5);
1048 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1049 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1050 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1052 rDateTime
.SetMonth(6);
1055 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1056 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1057 (pStart
[2] == 'l' || pStart
[2] == 'L') )
1059 rDateTime
.SetMonth(7);
1062 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1063 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1064 (pStart
[2] == 'g' || pStart
[2] == 'G') )
1066 rDateTime
.SetMonth(8);
1069 if ((pStart
[0] == 's' || pStart
[0] == 'S') &&
1070 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1071 (pStart
[2] == 'p' || pStart
[2] == 'P') )
1073 rDateTime
.SetMonth(9);
1076 if ((pStart
[0] == 'o' || pStart
[0] == 'O') &&
1077 (pStart
[1] == 'c' || pStart
[1] == 'C') &&
1078 (pStart
[2] == 't' || pStart
[2] == 'T') )
1080 rDateTime
.SetMonth(10);
1083 if ((pStart
[0] == 'n' || pStart
[0] == 'N') &&
1084 (pStart
[1] == 'o' || pStart
[1] == 'O') &&
1085 (pStart
[2] == 'v' || pStart
[2] == 'V') )
1087 rDateTime
.SetMonth(11);
1090 if ((pStart
[0] == 'd' || pStart
[0] == 'D') &&
1091 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1092 (pStart
[2] == 'c' || pStart
[2] == 'C') )
1094 rDateTime
.SetMonth(12);
1101 * parseUNIX_isDayField.
1103 bool FTPDirectoryParser::parseUNIX_isDayField (
1106 DateTime
&rDateTime
)
1108 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1110 if (*pStart
< '0' || *pStart
> '9')
1113 sal_uInt16 nDay
= *pStart
- '0';
1114 if (pStart
+ 1 < pEnd
)
1116 if (pStart
+ 2 != pEnd
|| pStart
[1] < '0' || pStart
[1] > '9')
1118 nDay
= 10 * nDay
+ (pStart
[1] - '0');
1120 if (!nDay
|| nDay
> 31)
1123 rDateTime
.SetDay(nDay
);
1128 * parseUNIX_isYearTimeField.
1130 bool FTPDirectoryParser::parseUNIX_isYearTimeField (
1133 DateTime
&rDateTime
)
1135 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
||
1136 *pStart
< '0' || *pStart
> '9')
1139 sal_uInt16 nNumber
= *pStart
- '0';
1145 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1146 if (*pStart
< '0' || *pStart
> '9')
1149 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1155 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1156 if (*pStart
< '0' || *pStart
> '9')
1159 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1162 if (pStart
== pEnd
|| *pStart
< '0' || *pStart
> '9')
1165 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1166 if (pStart
+ 1 != pEnd
|| nNumber
< 1970)
1169 rDateTime
.SetYear(nNumber
);
1170 rDateTime
.SetTime();
1177 bool FTPDirectoryParser::parseUNIX_isTime (
1181 DateTime
&rDateTime
)
1183 if ((nHour
> 23 ) || (pStart
+ 3 != pEnd
) ||
1184 (pStart
[1] < '0') || (pStart
[1] > '5') ||
1185 (pStart
[2] < '0') || (pStart
[2] > '9') )
1188 sal_uInt16 nMin
= 10 * (pStart
[1] - '0') + (pStart
[2] - '0');
1190 rDateTime
.SetHour (nHour
);
1191 rDateTime
.SetMin (nMin
);
1192 rDateTime
.SetSec (0);
1193 rDateTime
.SetNanoSec (0);
1196 // if (rDateTime.GetMonth() > aCurDate.GetMonth())
1197 // rDateTime.SetYear(aCurDate.GetYear() - 1);
1199 // rDateTime.SetYear(aCurDate.GetYear());
1203 osl_getSystemTime(&aTimeVal
);
1204 oslDateTime aCurrDateTime
;
1205 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1207 if (rDateTime
.GetMonth() > aCurrDateTime
.Month
)
1208 rDateTime
.SetYear(aCurrDateTime
.Year
- 1);
1210 rDateTime
.SetYear(aCurrDateTime
.Year
);
1217 * Two-digit years are taken as within 50 years back and 49 years forward
1218 * (both ends inclusive) from the current year. The returned date is not
1219 * checked for validity of the given day in the given month and year.
1222 void FTPDirectoryParser::setYear (
1223 DateTime
&rDateTime
, sal_uInt16 nYear
)
1228 osl_getSystemTime(&aTimeVal
);
1229 oslDateTime aCurrDateTime
;
1230 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1231 sal_uInt16 nCurrentYear
= aCurrDateTime
.Year
;
1232 // sal_uInt16 nCurrentYear = Date().GetYear();
1233 sal_uInt16 nCurrentCentury
= nCurrentYear
/ 100;
1234 nCurrentYear
%= 100;
1235 if (nCurrentYear
< 50)
1236 if (nYear
<= nCurrentYear
)
1237 nYear
+= nCurrentCentury
* 100;
1238 else if (nYear
< nCurrentYear
+ 50)
1239 nYear
+= nCurrentCentury
* 100;
1241 nYear
+= (nCurrentCentury
- 1) * 100;
1243 if (nYear
>= nCurrentYear
)
1244 nYear
+= nCurrentCentury
* 100;
1245 else if (nYear
>= nCurrentYear
- 50)
1246 nYear
+= nCurrentCentury
* 100;
1248 nYear
+= (nCurrentCentury
+ 1) * 100;
1251 rDateTime
.SetYear(nYear
);
1257 bool FTPDirectoryParser::setPath (
1258 OUString
&rPath
, const char *value
, sal_Int32 length
)
1263 length
= rtl_str_getLength (value
);
1264 rPath
= OUString (value
, length
, RTL_TEXTENCODING_UTF8
);
1269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */