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 using ::rtl::OUString
;
33 typedef sal_uInt32 ULONG
;
36 inline sal_Bool
ascii_isLetter( sal_Unicode ch
)
38 return (( (ch
>= 0x0041) && (ch
<= 0x005A)) ||
39 (( ch
>= 0x0061) && (ch
<= 0x007A)));
42 inline sal_Bool
ascii_isWhitespace( sal_Unicode ch
)
44 return ((ch
<= 0x20) && ch
);
49 /*========================================================================
51 * FTPDirectoryParser implementation.
53 *======================================================================*/
56 * Accepts one of two styles:
58 * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP
59 * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP
60 * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET
62 * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name
64 * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT
65 * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET
67 * interpreted as: size attribs DIR mm-dd-yy hh:mm name
70 sal_Bool
FTPDirectoryParser::parseDOS (
72 const sal_Char
*pBuffer
)
74 sal_Bool bDirectory
= false;
77 sal_uInt16 nMonth
= 0;
80 sal_uInt16 nMinute
= 0;
86 STATE_1_DAY
, STATE_1_YEAR
, STATE_1_YEAR_LWS
, STATE_1_HOUR
,
87 STATE_1_MINUTE
, STATE_1_MINUTE_LWS
, STATE_1_AP
,
88 STATE_1_APM
, STATE_1_LESS
, STATE_1_D
, STATE_1_DI
,
89 STATE_1_DIR
, STATE_1_SIZE
,
90 STATE_2_SIZE
, STATE_2_SIZE_LWS
, STATE_2_ATTRIB
,
91 STATE_2_D
, STATE_2_DI
, STATE_2_DIR_LWS
,
92 STATE_2_MONTH
, STATE_2_DAY
, STATE_2_YEAR
, STATE_2_YEAR_LWS
,
93 STATE_2_HOUR
, STATE_2_MINUTE
,
99 enum StateType eState
= STATE_INIT_LWS
;
100 for (const sal_Char
*p
= pBuffer
;
101 eState
!= STATE_ERROR
&& *p
;
107 if (*p
>= '0' && *p
<= '9')
111 eState
= STATE_MONTH_OR_SIZE
;
113 else if (!ascii_isWhitespace(*p
))
114 eState
= STATE_ERROR
;
117 case STATE_MONTH_OR_SIZE
:
118 if (*p
>= '0' && *p
<= '9')
120 nMonth
= 10 * nMonth
+ (*p
- '0');
127 eState
= STATE_2_SIZE
;
130 else if (ascii_isWhitespace(*p
))
134 eState
= STATE_2_SIZE_LWS
;
136 else if ((*p
== '.' || *p
== '-') && nMonth
&& nMonth
<= 12)
139 eState
= STATE_1_DAY
;
142 eState
= STATE_ERROR
;
146 if (*p
>= '0' && *p
<= '9')
149 nDay
= 10 * nDay
+ (*p
- '0');
153 eState
= STATE_ERROR
;
154 else if ((*p
== '.' || *p
== '-') && nDay
&& nDay
<= 31)
157 eState
= STATE_1_YEAR
;
160 eState
= STATE_ERROR
;
164 if (*p
>= '0' && *p
<= '9')
168 nYear
= 10 * nYear
+ (*p
- '0');
172 eState
= STATE_ERROR
;
176 if (ascii_isWhitespace(*p
))
177 eState
= STATE_1_YEAR_LWS
;
179 eState
= STATE_ERROR
;
183 case STATE_1_YEAR_LWS
:
184 if (*p
>= '0' && *p
<= '9')
188 eState
= STATE_1_HOUR
;
190 else if (!ascii_isWhitespace(*p
))
191 eState
= STATE_ERROR
;
195 if (*p
>= '0' && *p
<= '9')
198 nHour
= 10 * nHour
+ (*p
- '0');
202 eState
= STATE_ERROR
;
203 else if (*p
== ':' && nHour
< 24)
206 eState
= STATE_1_MINUTE
;
209 eState
= STATE_ERROR
;
213 if (*p
>= '0' && *p
<= '9')
216 nMinute
= 10 * nMinute
+ (*p
- '0');
220 eState
= STATE_ERROR
;
221 else if ((*p
== 'a' || *p
== 'A') && nMinute
< 60)
222 if (nHour
>= 1 && nHour
<= 11)
224 else if (nHour
== 12)
230 eState
= STATE_ERROR
;
231 else if ((*p
== 'p' || *p
== 'P') && nMinute
< 60)
232 if (nHour
>= 1 && nHour
<= 11)
237 else if (nHour
== 12)
240 eState
= STATE_ERROR
;
241 else if (ascii_isWhitespace(*p
) && (nMinute
< 60))
242 eState
= STATE_1_MINUTE_LWS
;
244 eState
= STATE_ERROR
;
247 case STATE_1_MINUTE_LWS
:
248 if (*p
== 'a' || *p
== 'A')
249 if (nHour
>= 1 && nHour
<= 11)
251 else if (nHour
== 12)
257 eState
= STATE_ERROR
;
258 else if (*p
== 'p' || *p
== 'P')
259 if (nHour
>= 1 && nHour
<= 11)
264 else if (nHour
== 12)
267 eState
= STATE_ERROR
;
269 eState
= STATE_1_LESS
;
270 else if (*p
>= '0' && *p
<= '9')
273 eState
= STATE_1_SIZE
;
275 else if (!ascii_isWhitespace(*p
))
276 eState
= STATE_ERROR
;
280 eState
= *p
== 'm' || *p
== 'M' ? STATE_1_APM
: STATE_ERROR
;
285 eState
= STATE_1_LESS
;
286 else if (*p
>= '0' && *p
<= '9')
289 eState
= STATE_1_SIZE
;
291 else if (!ascii_isWhitespace(*p
))
292 eState
= STATE_ERROR
;
296 eState
= *p
== 'd' || *p
== 'D' ? STATE_1_D
: STATE_ERROR
;
300 eState
= *p
== 'i' || *p
== 'I' ? STATE_1_DI
: STATE_ERROR
;
304 eState
= *p
== 'r' || *p
== 'R' ? STATE_1_DIR
: STATE_ERROR
;
311 eState
= STATE_LWS_NAME
;
314 eState
= STATE_ERROR
;
318 if (*p
>= '0' && *p
<= '9')
319 nSize
= 10 * nSize
+ (*p
- '0');
320 else if (ascii_isWhitespace(*p
))
321 eState
= STATE_LWS_NAME
;
323 eState
= STATE_ERROR
;
327 if (*p
>= '0' && *p
<= '9')
328 nSize
= 10 * nSize
+ (*p
- '0');
329 else if (ascii_isWhitespace(*p
))
330 eState
= STATE_2_SIZE_LWS
;
332 eState
= STATE_ERROR
;
335 case STATE_2_SIZE_LWS
:
336 if (*p
== 'd' || *p
== 'D')
338 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
339 eState
= STATE_2_ATTRIB
;
340 else if (*p
>= '0' && *p
<= '9')
344 eState
= STATE_2_MONTH
;
346 else if (!ascii_isWhitespace(*p
))
347 eState
= STATE_ERROR
;
351 if (ascii_isWhitespace(*p
))
352 eState
= STATE_2_SIZE_LWS
;
353 else if ((*p
< 'a' || *p
> 'z') && (*p
< 'A' || *p
> 'Z'))
354 eState
= STATE_ERROR
;
358 if (*p
== 'i' || *p
== 'I')
360 else if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
361 eState
= STATE_2_ATTRIB
;
362 else if (ascii_isWhitespace(*p
))
363 eState
= STATE_2_SIZE_LWS
;
365 eState
= STATE_ERROR
;
369 if (*p
== 'r' || *p
== 'R')
372 eState
= STATE_2_DIR_LWS
;
376 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z'))
377 eState
= STATE_2_ATTRIB
;
378 else if (ascii_isWhitespace(*p
))
379 eState
= STATE_2_SIZE_LWS
;
381 eState
= STATE_ERROR
;
385 case STATE_2_DIR_LWS
:
386 if (*p
>= '0' && *p
<= '9')
390 eState
= STATE_2_MONTH
;
392 else if (!ascii_isWhitespace(*p
))
393 eState
= STATE_ERROR
;
397 if (*p
>= '0' && *p
<= '9')
400 nMonth
= 10 * nMonth
+ (*p
- '0');
404 eState
= STATE_ERROR
;
405 else if (*p
== '-' && nMonth
&& nMonth
<= 12)
408 eState
= STATE_2_DAY
;
411 eState
= STATE_ERROR
;
415 if (*p
>= '0' && *p
<= '9')
418 nDay
= 10 * nDay
+ (*p
- '0');
422 eState
= STATE_ERROR
;
423 else if (*p
== '-' && nDay
&& nDay
<= 31)
426 eState
= STATE_2_YEAR
;
429 eState
= STATE_ERROR
;
433 if (*p
>= '0' && *p
<= '9')
437 nYear
= 10 * nYear
+ (*p
- '0');
441 eState
= STATE_ERROR
;
445 if (ascii_isWhitespace(*p
))
446 eState
= STATE_2_YEAR_LWS
;
448 eState
= STATE_ERROR
;
452 case STATE_2_YEAR_LWS
:
453 if (*p
>= '0' && *p
<= '9')
457 eState
= STATE_2_HOUR
;
459 else if (!ascii_isWhitespace(*p
))
460 eState
= STATE_ERROR
;
464 if (*p
>= '0' && *p
<= '9')
467 nHour
= 10 * nHour
+ (*p
- '0');
471 eState
= STATE_ERROR
;
472 else if (*p
== ':' && nHour
< 24)
475 eState
= STATE_2_MINUTE
;
478 eState
= STATE_ERROR
;
482 if (*p
>= '0' && *p
<= '9')
486 nMinute
= 10 * nMinute
+ (*p
- '0');
490 eState
= STATE_ERROR
;
494 if (ascii_isWhitespace(*p
) && (nMinute
< 60))
495 eState
= STATE_LWS_NAME
;
497 eState
= STATE_ERROR
;
502 if (!ascii_isWhitespace(*p
))
504 setPath (rEntry
.m_aName
, p
);
506 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
507 rEntry
.m_nSize
= nSize
;
509 setYear (rEntry
.m_aDate
, nYear
);
511 rEntry
.m_aDate
.SetMonth(nMonth
);
512 rEntry
.m_aDate
.SetDay(nDay
);
513 rEntry
.m_aDate
.SetHour(nHour
);
514 rEntry
.m_aDate
.SetMin(nMinute
);
529 * Directory entries may span one or two lines:
531 * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest
533 * name: filename "." filetype ";" version
534 * filename: 1*39fchar
535 * filetype: 1*39fchar
536 * version: non0digit *digit
538 * size: "0" / non0digit *digit
540 * datetime: date 1*lwsp time
541 * date: day "-" month "-" year
542 * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1")
543 * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG"
544 * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive
545 * year: 2digit / 4digit
546 * time: hour ":" minute
547 * hour: ((*1"0" / "1") digit) / ("2" "0"-"3")
548 * minute: "0"-"5" digit
550 * rest: *1(lws *<ANY>)
552 * lws: <TAB> / <SPACE>
554 * digit: "0" / non0digit
555 * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$"
557 * For directories, the returned name is the <filename> part; for non-
558 * directory files, the returned name is the <filename "." filetype> part.
559 * An entry is a directory iff its filetype is "DIR" (ignoring case).
561 * The READ, WRITE, and ISLINK mode bits are not supported.
563 * The returned size is the <size> part, multiplied by 512, and with the high
564 * order bits truncated to fit into a ULONG.
567 sal_Bool
FTPDirectoryParser::parseVMS (
569 const sal_Char
*pBuffer
)
571 static OUString aFirstLineName
;
572 static sal_Bool bFirstLineDir
= sal_False
;
574 for (sal_Bool bFirstLine
= sal_True
;; bFirstLine
= sal_False
)
576 const sal_Char
*p
= pBuffer
;
580 while (*p
== '\t' || *p
== ' ')
583 // Parse <filename "."> part:
584 const sal_Char
*pFileName
= p
;
585 while ((*p
>= 'A' && *p
<= 'Z') ||
586 (*p
>= 'a' && *p
<= 'z') ||
587 (*p
>= '0' && *p
<= '9') ||
588 *p
== '-' || *p
== '_' || *p
== '$')
591 if (*p
!= '.' || p
== pFileName
|| p
- pFileName
> 39)
593 if (!aFirstLineName
.isEmpty())
599 // Parse <filetype ";"> part:
600 const sal_Char
*pFileType
= ++p
;
601 while ((*p
>= 'A' && *p
<= 'Z') ||
602 (*p
>= 'a' && *p
<= 'z') ||
603 (*p
>= '0' && *p
<= '9') ||
604 *p
== '-' || *p
== '_' || *p
== '$')
607 if (*p
!= ';' || p
== pFileName
|| p
- pFileName
> 39)
609 if (!aFirstLineName
.isEmpty())
616 // Set entry's name and mode (ISDIR flag):
617 if ((p
- pFileType
== 4) &&
618 (pFileType
[0] == 'D' || pFileType
[0] == 'd') &&
619 (pFileType
[1] == 'I' || pFileType
[1] == 'i') &&
620 (pFileType
[2] == 'R' || pFileType
[2] == 'r') )
622 setPath (rEntry
.m_aName
, pFileName
, (pFileType
- pFileName
));
623 rEntry
.m_nMode
= INETCOREFTP_FILEMODE_ISDIR
;
627 setPath (rEntry
.m_aName
, pFileName
, (p
- pFileName
));
631 // Skip <version> part:
632 if (*p
< '1' || *p
> '9')
634 if (!aFirstLineName
.isEmpty())
640 while (*p
>= '0' && *p
<= '9')
643 // Parse <1*lws> or <*lws <NEWLINE>> part:
644 sal_Bool bLWS
= false;
645 while (*p
== '\t' || *p
== ' ')
654 if (!aFirstLineName
.isEmpty())
663 * First line of entry spanning two lines,
664 * wait for second line.
666 aFirstLineName
= rEntry
.m_aName
;
668 ((rEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
) != 0);
675 * Second line of entry spanning two lines,
676 * restore entry's name and mode (ISDIR flag).
678 rEntry
.m_aName
= aFirstLineName
;
679 rEntry
.m_nMode
= (bFirstLineDir
? INETCOREFTP_FILEMODE_ISDIR
: 0);
681 // Skip <1*lws> part:
682 if (*p
!= '\t' && *p
!= ' ')
685 while (*p
== '\t' || *p
== ' ')
689 // Parse <size> part and set entry's size:
690 if (*p
< '0' || *p
> '9')
692 ULONG nSize
= *p
- '0';
694 while (*p
>= '0' && *p
<= '9')
695 nSize
= 10 * rEntry
.m_nSize
+ (*p
++ - '0');
696 rEntry
.m_nSize
= 512 * nSize
;
698 // Skip <1*lws> part:
699 if (*p
!= '\t' && *p
!= ' ')
702 while (*p
== '\t' || *p
== ' ')
705 // Parse <day "-"> part and set entry date's day:
710 if (*p
< '1' || *p
> '9')
714 else if (*p
== '1' || *p
== '2')
717 if (*p
>= '0' && *p
<= '9')
718 nDay
= 10 * nDay
+ (*p
++ - '0');
723 nDay
= (*p
== '0' || *p
== '1') ? 30 + (*p
++ - '0') : 3;
725 else if (*p
>= '4' && *p
<= '9')
730 rEntry
.m_aDate
.SetDay(nDay
);
734 // Parse <month "-"> part and set entry date's month:
735 sal_Char
const * pMonth
= p
;
736 sal_Int32
const monthLen
= 3;
737 for (int i
= 0; i
< monthLen
; ++i
)
739 if (!((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z')))
743 if (rtl_str_compareIgnoreAsciiCase_WithLength(
744 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JAN")) == 0)
745 rEntry
.m_aDate
.SetMonth(1);
746 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
747 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("FEB")) == 0)
748 rEntry
.m_aDate
.SetMonth(2);
749 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
750 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("MAR")) == 0)
751 rEntry
.m_aDate
.SetMonth(3);
752 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
753 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("APR")) == 0)
754 rEntry
.m_aDate
.SetMonth(4);
755 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
756 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("MAY")) == 0)
757 rEntry
.m_aDate
.SetMonth(5);
758 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
759 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JUN")) == 0)
760 rEntry
.m_aDate
.SetMonth(6);
761 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
762 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("JUL")) == 0)
763 rEntry
.m_aDate
.SetMonth(7);
764 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
765 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("AUG")) == 0)
766 rEntry
.m_aDate
.SetMonth(8);
767 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
768 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("SEP")) == 0)
769 rEntry
.m_aDate
.SetMonth(9);
770 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
771 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("OCT")) == 0)
772 rEntry
.m_aDate
.SetMonth(10);
773 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
774 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("NOV")) == 0)
775 rEntry
.m_aDate
.SetMonth(11);
776 else if (rtl_str_compareIgnoreAsciiCase_WithLength(
777 pMonth
, monthLen
, RTL_CONSTASCII_STRINGPARAM("DEC")) == 0)
778 rEntry
.m_aDate
.SetMonth(12);
784 // Parse <year> part and set entry date's year:
785 sal_uInt16 nYear
= 0;
786 {for (int i
= 0; i
< 2; ++i
)
788 if (*p
< '0' || *p
> '9')
790 nYear
= 10 * nYear
+ (*p
++ - '0');
792 if (*p
>= '0' && *p
<= '9')
794 nYear
= 10 * nYear
+ (*p
++ - '0');
795 if (*p
< '0' || *p
> '9')
797 nYear
= 10 * nYear
+ (*p
++ - '0');
799 setYear (rEntry
.m_aDate
, nYear
);
801 // Skip <1*lws> part:
802 if (*p
!= '\t' && *p
!= ' ')
805 while (*p
== '\t' || *p
== ' ')
808 // Parse <hour ":"> part and set entry time's hour:
810 if (*p
== '0' || *p
== '1')
813 if (*p
>= '0' && *p
<= '9')
814 nHour
= 10 * nHour
+ (*p
++ - '0');
819 nHour
= (*p
>= '0' && *p
<= '3') ? 20 + (*p
++ - '0') : 2;
821 else if (*p
>= '3' && *p
<= '9')
826 rEntry
.m_aDate
.SetHour(nHour
);
831 * Parse <minute> part and set entry time's minutes,
832 * seconds (0), and 1/100 seconds (0).
834 if (*p
< '0' || *p
> '5')
837 sal_uInt16 nMinute
= *p
++ - '0';
838 if (*p
< '0' || *p
> '9')
841 nMinute
= 10 * nMinute
+ (*p
++ - '0');
842 rEntry
.m_aDate
.SetMin(nMinute
);
843 rEntry
.m_aDate
.SetSec(0);
844 rEntry
.m_aDate
.Set100Sec(0);
847 if (*p
&& (*p
!= '\t' && *p
!= ' '))
857 sal_Bool
FTPDirectoryParser::parseUNIX (
859 const sal_Char
*pBuffer
)
861 const sal_Char
*p1
, *p2
;
864 if (!((*p1
== '-') || (*p1
== 'd') || (*p1
== 'l')))
867 // 1st column: FileMode.
869 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISDIR
;
872 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_ISLINK
;
874 // Skip to end of column and set rights by the way
875 while (*p1
&& !ascii_isWhitespace(*p1
)) {
877 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_READ
;
879 rEntry
.m_nMode
|= INETCOREFTP_FILEMODE_WRITE
;
884 * Scan for the sequence of size and date fields:
885 * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS
886 * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS
890 FOUND_NONE
, FOUND_SIZE
, FOUND_MONTH
, FOUND_DAY
, FOUND_YEAR_TIME
893 const sal_Char
*pDayStart
= 0;
894 const sal_Char
*pDayEnd
= 0;
896 for (eMode
= FOUND_NONE
; *p1
&& eMode
!= FOUND_YEAR_TIME
; p1
= p2
+ 1)
898 while (*p1
&& ascii_isWhitespace(*p1
))
901 while (*p2
&& !ascii_isWhitespace(*p2
))
907 if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
912 if (parseUNIX_isMonthField (p1
, p2
, rEntry
.m_aDate
))
914 else if (!parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
919 if (parseUNIX_isDayField (p1
, p2
, rEntry
.m_aDate
))
925 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
932 if (parseUNIX_isYearTimeField (p1
, p2
, rEntry
.m_aDate
))
933 eMode
= FOUND_YEAR_TIME
;
935 parseUNIX_isSizeField (
936 pDayStart
, pDayEnd
, rEntry
.m_nSize
) &&
937 parseUNIX_isMonthField (
938 p1
, p2
, rEntry
.m_aDate
))
940 else if (parseUNIX_isSizeField (p1
, p2
, rEntry
.m_nSize
))
945 case FOUND_YEAR_TIME
:
950 if (eMode
== FOUND_YEAR_TIME
)
952 // 9th column: FileName (rest of line).
953 while (*p1
&& ascii_isWhitespace(*p1
)) p1
++;
954 setPath (rEntry
.m_aName
, p1
);
963 * parseUNIX_isSizeField.
965 sal_Bool
FTPDirectoryParser::parseUNIX_isSizeField (
966 const sal_Char
*pStart
,
967 const sal_Char
*pEnd
,
970 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
974 if (*pStart
>= '0' && *pStart
<= '9')
976 for (; pStart
< pEnd
; ++pStart
)
977 if ((*pStart
>= '0') && (*pStart
<= '9'))
978 rSize
= 10 * rSize
+ (*pStart
- '0');
986 * For a combination of long group name and large file size,
987 * some FTPDs omit LWS between those two columns.
992 for (; pStart
< pEnd
; ++pStart
)
993 if ((*pStart
>= '1') && (*pStart
<= '9'))
996 rSize
= 10 * rSize
+ (*pStart
- '0');
998 else if ((*pStart
== '0') && nDigits
)
1003 else if ((*pStart
> ' ') && (sal::static_int_cast
<sal_uInt8
>(*pStart
) <= '\x7F'))
1005 nNonDigits
+= nDigits
+ 1;
1011 return ((nNonDigits
>= 9) && (nDigits
>= 7));
1016 * parseUNIX_isMonthField.
1018 sal_Bool
FTPDirectoryParser::parseUNIX_isMonthField (
1019 const sal_Char
*pStart
,
1020 const sal_Char
*pEnd
,
1021 DateTime
&rDateTime
)
1023 if (!*pStart
|| !*pEnd
|| pStart
+ 3 != pEnd
)
1026 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1027 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1028 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1030 rDateTime
.SetMonth(1);
1033 if ((pStart
[0] == 'f' || pStart
[0] == 'F') &&
1034 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1035 (pStart
[2] == 'b' || pStart
[2] == 'B') )
1037 rDateTime
.SetMonth(2);
1040 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1041 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1042 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1044 rDateTime
.SetMonth(3);
1047 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1048 (pStart
[1] == 'p' || pStart
[1] == 'P') &&
1049 (pStart
[2] == 'r' || pStart
[2] == 'R') )
1051 rDateTime
.SetMonth(4);
1054 if ((pStart
[0] == 'm' || pStart
[0] == 'M') &&
1055 (pStart
[1] == 'a' || pStart
[1] == 'A') &&
1056 (pStart
[2] == 'y' || pStart
[2] == 'Y') )
1058 rDateTime
.SetMonth(5);
1061 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1062 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1063 (pStart
[2] == 'n' || pStart
[2] == 'N') )
1065 rDateTime
.SetMonth(6);
1068 if ((pStart
[0] == 'j' || pStart
[0] == 'J') &&
1069 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1070 (pStart
[2] == 'l' || pStart
[2] == 'L') )
1072 rDateTime
.SetMonth(7);
1075 if ((pStart
[0] == 'a' || pStart
[0] == 'A') &&
1076 (pStart
[1] == 'u' || pStart
[1] == 'U') &&
1077 (pStart
[2] == 'g' || pStart
[2] == 'G') )
1079 rDateTime
.SetMonth(8);
1082 if ((pStart
[0] == 's' || pStart
[0] == 'S') &&
1083 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1084 (pStart
[2] == 'p' || pStart
[2] == 'P') )
1086 rDateTime
.SetMonth(9);
1089 if ((pStart
[0] == 'o' || pStart
[0] == 'O') &&
1090 (pStart
[1] == 'c' || pStart
[1] == 'C') &&
1091 (pStart
[2] == 't' || pStart
[2] == 'T') )
1093 rDateTime
.SetMonth(10);
1096 if ((pStart
[0] == 'n' || pStart
[0] == 'N') &&
1097 (pStart
[1] == 'o' || pStart
[1] == 'O') &&
1098 (pStart
[2] == 'v' || pStart
[2] == 'V') )
1100 rDateTime
.SetMonth(11);
1103 if ((pStart
[0] == 'd' || pStart
[0] == 'D') &&
1104 (pStart
[1] == 'e' || pStart
[1] == 'E') &&
1105 (pStart
[2] == 'c' || pStart
[2] == 'C') )
1107 rDateTime
.SetMonth(12);
1114 * parseUNIX_isDayField.
1116 sal_Bool
FTPDirectoryParser::parseUNIX_isDayField (
1117 const sal_Char
*pStart
,
1118 const sal_Char
*pEnd
,
1119 DateTime
&rDateTime
)
1121 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
)
1123 if (*pStart
< '0' || *pStart
> '9')
1126 sal_uInt16 nDay
= *pStart
- '0';
1127 if (pStart
+ 1 < pEnd
)
1129 if (pStart
+ 2 != pEnd
|| pStart
[1] < '0' || pStart
[1] > '9')
1131 nDay
= 10 * nDay
+ (pStart
[1] - '0');
1133 if (!nDay
|| nDay
> 31)
1136 rDateTime
.SetDay(nDay
);
1141 * parseUNIX_isYearTimeField.
1143 sal_Bool
FTPDirectoryParser::parseUNIX_isYearTimeField (
1144 const sal_Char
*pStart
,
1145 const sal_Char
*pEnd
,
1146 DateTime
&rDateTime
)
1148 if (!*pStart
|| !*pEnd
|| pStart
== pEnd
||
1149 *pStart
< '0' || *pStart
> '9')
1152 sal_uInt16 nNumber
= *pStart
- '0';
1158 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1159 if (*pStart
< '0' || *pStart
> '9')
1162 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1168 return parseUNIX_isTime (pStart
, pEnd
, nNumber
, rDateTime
);
1169 if (*pStart
< '0' || *pStart
> '9')
1172 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1175 if (pStart
== pEnd
|| *pStart
< '0' || *pStart
> '9')
1178 nNumber
= 10 * nNumber
+ (*pStart
- '0');
1179 if (pStart
+ 1 != pEnd
|| nNumber
< 1970)
1182 rDateTime
.SetYear(nNumber
);
1183 rDateTime
.SetTime(0);
1190 sal_Bool
FTPDirectoryParser::parseUNIX_isTime (
1191 const sal_Char
*pStart
,
1192 const sal_Char
*pEnd
,
1194 DateTime
&rDateTime
)
1196 if ((nHour
> 23 ) || (pStart
+ 3 != pEnd
) ||
1197 (pStart
[1] < '0') || (pStart
[1] > '5') ||
1198 (pStart
[2] < '0') || (pStart
[2] > '9') )
1201 sal_uInt16 nMin
= 10 * (pStart
[1] - '0') + (pStart
[2] - '0');
1203 rDateTime
.SetHour (nHour
);
1204 rDateTime
.SetMin (nMin
);
1205 rDateTime
.SetSec (0);
1206 rDateTime
.Set100Sec (0);
1209 // if (rDateTime.GetMonth() > aCurDate.GetMonth())
1210 // rDateTime.SetYear(aCurDate.GetYear() - 1);
1212 // rDateTime.SetYear(aCurDate.GetYear());
1216 osl_getSystemTime(&aTimeVal
);
1217 oslDateTime aCurrDateTime
;
1218 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1220 if (rDateTime
.GetMonth() > aCurrDateTime
.Month
)
1221 rDateTime
.SetYear(aCurrDateTime
.Year
- 1);
1223 rDateTime
.SetYear(aCurrDateTime
.Year
);
1230 * Two-digit years are taken as within 50 years back and 49 years forward
1231 * (both ends inclusive) from the current year. The returned date is not
1232 * checked for validity of the given day in the given month and year.
1235 sal_Bool
FTPDirectoryParser::setYear (
1236 DateTime
&rDateTime
, sal_uInt16 nYear
)
1241 osl_getSystemTime(&aTimeVal
);
1242 oslDateTime aCurrDateTime
;
1243 osl_getDateTimeFromTimeValue(&aTimeVal
,&aCurrDateTime
);
1244 sal_uInt16 nCurrentYear
= aCurrDateTime
.Year
;
1245 // sal_uInt16 nCurrentYear = Date().GetYear();
1246 sal_uInt16 nCurrentCentury
= nCurrentYear
/ 100;
1247 nCurrentYear
%= 100;
1248 if (nCurrentYear
< 50)
1249 if (nYear
<= nCurrentYear
)
1250 nYear
+= nCurrentCentury
* 100;
1251 else if (nYear
< nCurrentYear
+ 50)
1252 nYear
+= nCurrentCentury
* 100;
1254 nYear
+= (nCurrentCentury
- 1) * 100;
1256 if (nYear
>= nCurrentYear
)
1257 nYear
+= nCurrentCentury
* 100;
1258 else if (nYear
>= nCurrentYear
- 50)
1259 nYear
+= nCurrentCentury
* 100;
1261 nYear
+= (nCurrentCentury
+ 1) * 100;
1264 rDateTime
.SetYear(nYear
);
1271 sal_Bool
FTPDirectoryParser::setPath (
1272 OUString
&rPath
, const sal_Char
*value
, sal_Int32 length
)
1277 length
= rtl_str_getLength (value
);
1278 rPath
= OUString (value
, length
, RTL_TEXTENCODING_UTF8
);
1283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */