+#if defined(HAVE_TANDEM)\r
+ case LIST_TANDEM :\r
+ *InfoExist |= (FINFO_TIME | FINFO_DATE | FINFO_SIZE | FINFO_ATTR);\r
+ /* Open 中だったらずらす */\r
+ if(FindField(Str, Buf, 1, NO) != FFFTP_SUCCESS)\r
+ break;\r
+ if (!strncmp(Buf, "O", 1)) {\r
+ offs = 1;\r
+ }\r
+ /* 日付 */\r
+ if(FindField(Str, Buf, 3 + offs, NO) != FFFTP_SUCCESS)\r
+ break;\r
+ if (Buf[1] == '-') { /* 日付が 1桁 */\r
+ sTime.wYear = Assume1900or2000(atoi(Buf + 6));\r
+ Buf[5] = 0;\r
+ GetMonth(Buf+2, &sTime.wMonth, &sTime.wDay); /* wDayは常に0 */\r
+ sTime.wDay = atoi(Buf);\r
+ sTime.wDayOfWeek = 0;\r
+ } else {\r
+ sTime.wYear = Assume1900or2000(atoi(Buf + 7));\r
+ Buf[6] = 0;\r
+ GetMonth(Buf+3, &sTime.wMonth, &sTime.wDay); /* wDayは常に0 */\r
+ sTime.wDay = atoi(Buf);\r
+ sTime.wDayOfWeek = 0;\r
+ }\r
+ /* 時刻 */\r
+ FindField(Str, Buf, 4 + offs, NO);\r
+ sTime.wHour = atoi(Buf);\r
+ sTime.wMinute = atoi(Buf+3);\r
+ sTime.wSecond = atoi(Buf+6);\r
+ sTime.wMilliseconds = 0;\r
+ SystemTimeToFileTime(&sTime, Time);\r
+ SpecificLocalFileTime2FileTime(Time, AskHostTimeZone());\r
+\r
+ /* 属性 セキュリティではなく FileCode を保存する */\r
+ FindField(Str, Buf, 1 + offs, NO);\r
+ *Attr = atoi(Buf);\r
+ /* サイズ */\r
+ FindField(Str, Buf, 2 + offs, NO);\r
+ *Size = _atoi64(Buf);\r
+ /* オーナ名 */\r
+ if(FindField(Str, Buf, 5 + offs, NO) == FFFTP_SUCCESS) {\r
+ if(strncmp(Buf, "Owner", sizeof("Owner"))) {\r
+ memset(Owner, NUL, OWNER_NAME_LEN+1);\r
+ strncpy(Owner, Buf, OWNER_NAME_LEN);\r
+ /* 通常は 255,255 だが、20, 33 などにも対応する */\r
+ /* 最後の文字が , だったら後ろとつなげる */\r
+ if (Buf[strlen(Buf)-1] == ',') {\r
+ FindField(Str, Buf, 6 + offs, NO);\r
+ strncat(Owner, Buf, OWNER_NAME_LEN - strlen(Buf));\r
+ }\r
+ /* ファイル名 */\r
+ if(FindField(Str, Fname, 0, NO) == FFFTP_SUCCESS) {\r
+ Ret = NODE_FILE;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+#endif\r
+\r
+ // MLSD対応\r
+ // 以下の形式に対応\r
+ // fact1=value1;fact2=value2;fact3=value3; filename\r\n\r
+ // 不完全な実装のホストが存在するため以下の形式も許容\r
+ // fact1=value1;fact2=value2;fact3=value3 filename\r\n\r
+ // fact1=value1;fact2=value2;fact3=value3;filename\r\n\r
+ // SymlinkはRFC3659の7.7.4. A More Complex Exampleに\r
+ // よるとtype=OS.unix=slink:(target)だが\r
+ // ProFTPDはtype=OS.unix=symlink:(target)となる\r
+ case LIST_MLSD:\r
+ {\r
+ int i = 0;\r
+ char StrBuf[(FMAX_PATH * 2) + 1];\r
+ char Fact[FMAX_PATH + 1];\r
+ char Name[FMAX_PATH + 1];\r
+ char Value[FMAX_PATH + 1];\r
+ char Value2[FMAX_PATH + 1];\r
+ char* pFileName;\r
+ strncpy(StrBuf, Str, FMAX_PATH * 2);\r
+ StrBuf[FMAX_PATH * 2] = '\0';\r
+ if((pFileName = strstr(StrBuf, "; ")) != NULL)\r
+ {\r
+ *pFileName = '\0';\r
+ pFileName += 2;\r
+ }\r
+ else if((pFileName = strchr(StrBuf, ' ')) != NULL)\r
+ {\r
+ *pFileName = '\0';\r
+ pFileName++;\r
+ }\r
+ else if((pFileName = strrchr(StrBuf, ';')) != NULL)\r
+ {\r
+ *pFileName = '\0';\r
+ pFileName++;\r
+ }\r
+ if(pFileName != NULL)\r
+ strcpy(Fname, pFileName);\r
+ while(FindField2(StrBuf, Fact, ';', i, NO) == FFFTP_SUCCESS)\r
+ {\r
+ if(FindField2(Fact, Name, '=', 0, NO) == FFFTP_SUCCESS && FindField2(Fact, Value, '=', 1, NO) == FFFTP_SUCCESS)\r
+ {\r
+ if(_stricmp(Name, "type") == 0)\r
+ {\r
+ if(_stricmp(Value, "dir") == 0)\r
+ Ret = NODE_DIR;\r
+ else if(_stricmp(Value, "file") == 0)\r
+ Ret = NODE_FILE;\r
+ else if(_stricmp(Value, "OS.unix") == 0)\r
+ if(FindField2(Fact, Value2, '=', 2, NO) == FFFTP_SUCCESS)\r
+ if(_stricmp(Value2, "symlink") == 0 || _stricmp(Value2, "slink") == 0) { // ProFTPD is symlink. A example of RFC3659 is slink.\r
+ Ret = NODE_DIR;\r
+ *Link = YES;\r
+ }\r
+ }\r
+ else if(_stricmp(Name, "size") == 0)\r
+ {\r
+ *Size = _atoi64(Value);\r
+ *InfoExist |= FINFO_SIZE;\r
+ }\r
+ else if(_stricmp(Name, "modify") == 0)\r
+ {\r
+ sTime.wYear = atoi_n(Value, 4);\r
+ sTime.wMonth = atoi_n(Value + 4, 2);\r
+ sTime.wDay = atoi_n(Value + 6, 2);\r
+ sTime.wHour = atoi_n(Value + 8, 2);\r
+ sTime.wMinute = atoi_n(Value + 10, 2);\r
+ sTime.wSecond = atoi_n(Value + 12, 2);\r
+ sTime.wMilliseconds = 0;\r
+ SystemTimeToFileTime(&sTime, Time);\r
+ // 時刻はGMT\r
+// SpecificLocalFileTime2FileTime(Time, AskHostTimeZone());\r
+ *InfoExist |= FINFO_DATE | FINFO_TIME;\r
+ }\r
+ else if(_stricmp(Name, "UNIX.mode") == 0)\r
+ {\r
+ *Attr = strtol(Value, NULL, 16);\r
+ *InfoExist |= FINFO_ATTR;\r
+ }\r
+ else if(_stricmp(Name, "UNIX.owner") == 0)\r
+ strcpy(Owner, Value);\r
+ }\r
+ i++;\r
+ }\r
+ }\r
+ break;\r
+\r