Ticket #5071: FixTicket5071_ZeroSecondsForSFTP.diff
File FixTicket5071_ZeroSecondsForSFTP.diff, 13.7 KB (added by , 13 years ago) |
---|
-
src/include/directorylisting.h
20 20 flag_timestamp_date = 0x10, 21 21 flag_timestamp_time = 0x20, 22 22 flag_timestamp_seconds = 0x40, 23 24 flag_timestamp_mask = 0x70 23 flag_timestamp_utc = 0x80, 24 25 flag_timestamp_mask = 0xF0 25 26 }; 26 27 int flags; 27 28 … … 51 52 { 52 53 return (flags & flag_timestamp_seconds) != 0; 53 54 } 55 inline bool is_utc() const 56 { 57 return (flags & flag_timestamp_utc) != 0; 58 } 59 inline void AdjustTimeToUTC ( const wxTimeSpan &span ) 60 { 61 if (has_time() && !is_utc()) 62 { 63 time.Add(span); 64 flags |= flag_timestamp_utc; 65 } 66 } 67 inline void AdjustTimeToUTC ( const int offset ) 68 { 69 if (offset) { 70 const wxTimeSpan span(0, offset, 0, 0); 71 AdjustTimeToUTC(span); 72 } 73 } 74 75 54 76 55 56 77 wxString target; // Set to linktarget it link is true 57 78 58 79 wxDateTime time; -
src/engine/directorylisting.cpp
151 151 if (iter->is_dir()) 152 152 m_hasDirs = true; 153 153 if (!iter->permissions.empty()) 154 m_has_perms = true; 155 if (!iter->ownerGroup.empty()) 154 156 m_has_usergroup = true; 155 if (!iter->ownerGroup.empty())156 m_has_perms = true;157 157 own_entries.push_back(CRefcountObject<CDirentry>(*iter)); 158 158 } 159 159 -
src/engine/directorylistingparser.h
49 49 void Reset(); 50 50 51 51 void SetTimezoneOffset(const wxTimeSpan& span) { m_timezoneOffset = span; } 52 53 void SetFilezillaDataFormat(const bool filezilla_format) { m_attributeState = attr_file_next; } 52 54 53 55 void SetServer(const CServer& server) { m_server = server; }; 54 56 55 57 protected: 58 59 enum attributeStates 60 { 61 attr_disabled = 0, 62 attr_file_next, 63 attr_keep_next, 64 attr_skip_next, 65 }; 66 56 67 CLine *GetLine(bool breakAtEnd, bool& error); 57 68 58 69 bool ParseData(bool partial); … … 82 93 // with other formats. 83 94 bool ParseAsHPNonstop(CLine *pLine, CDirentry &entry); 84 95 96 // When used with the Filezilla output format, parses attribute information 97 // provided by Filezilla's helper applications 98 bool ParseAsFilezillaAttributes(CLine *pLine, CDirentry &entry, bool ignoreBadPermissions); 99 85 100 // Date / time parsers 86 101 bool ParseUnixDateTime(CLine *pLine, int &index, CDirentry &entry); 87 102 bool ParseShortDate(CToken &token, CDirentry &entry, bool saneFieldOrder = false); … … 115 130 116 131 bool m_maybeMultilineVms; 117 132 133 int m_attributeState; 134 118 135 wxTimeSpan m_timezoneOffset; 119 136 }; 120 137 -
src/engine/sftpcontrolsocket.cpp
1083 1083 for (int i = 0; i < count; ++i) 1084 1084 { 1085 1085 CDirentry& entry = pData->directoryListing[i]; 1086 if (!entry.has_time())1087 continue;1088 1086 1089 entry. time += span;1087 entry.AdjustTimeToUTC (span); 1090 1088 } 1091 1089 1092 1090 // TODO: Correct cached listings … … 1261 1259 { 1262 1260 pData->pParser = new CDirectoryListingParser(this, *m_pCurrentServer); 1263 1261 pData->pParser->SetTimezoneOffset(GetTimezoneOffset()); 1264 if (!Send(_T("ls"))) 1262 pData->pParser->SetFilezillaDataFormat(true); 1263 if (!Send(_T("ls-fz"))) 1265 1264 return FZ_REPLY_ERROR; 1266 1265 return FZ_REPLY_WOULDBLOCK; 1267 1266 } -
src/engine/directorylistingparser.cpp
1 1 #include <filezilla.h> 2 #include <inttypes.h> 2 3 #include "directorylistingparser.h" 3 4 #include "ControlSocket.h" 4 5 … … 6 7 #define new DEBUG_NEW 7 8 #endif 8 9 10 9 11 std::map<wxString, int> CDirectoryListingParser::m_MonthNamesMap; 10 12 11 13 //#define LISTDEBUG_MVS … … 273 275 else if (c >= 'a' && c <= 'f') 274 276 { 275 277 number *= 16; 276 number += c - ' 0' + 10;278 number += c - 'a' + 10; 277 279 } 278 280 else if (c >= 'A' && c <= 'F') 279 281 { … … 454 456 m_prevLine = 0; 455 457 m_fileListOnly = true; 456 458 m_maybeMultilineVms = false; 459 m_attributeState = attr_disabled; 457 460 458 461 if (m_MonthNamesMap.empty()) 459 462 { … … 765 768 CDirentry entry; 766 769 bool res; 767 770 int ires; 768 771 772 if (m_attributeState != attr_disabled && 773 m_attributeState != attr_file_next) 774 { 775 switch (m_attributeState) 776 { 777 case attr_keep_next: 778 { 779 entry = m_entryList.back(); 780 781 res = ParseAsFilezillaAttributes(pLine, entry, false); 782 783 if (res) { 784 m_entryList.pop_back(); 785 m_entryList.push_back(entry); 786 } 787 } 788 break; 789 case attr_skip_next: 790 { 791 // "." and ".." don't get pushed onto m_entryList 792 res = ParseAsFilezillaAttributes(pLine, entry, true); 793 } 794 break; 795 default: 796 res = false; 797 break; 798 } 799 800 m_attributeState = attr_file_next; 801 if (res) 802 return res; 803 // On failure fall through to ensure that no directory lines are skipped 804 } 805 769 806 if (serverType == ZVM) 770 807 { 771 808 res = ParseAsZVM(pLine, entry); … … 864 901 m_fileList.clear(); 865 902 m_fileListOnly = false; 866 903 904 if (m_attributeState) 905 m_attributeState = attr_keep_next; 906 867 907 // Don't add . or .. 868 908 if (entry.name == _T(".") || entry.name == _T("..")) 909 { 910 if (m_attributeState) 911 m_attributeState = attr_skip_next; 869 912 return true; 913 } 870 914 871 915 if (serverType == VMS && entry.is_dir()) 872 916 { … … 876 920 entry.name = entry.name.Left(pos); 877 921 } 878 922 879 { 880 int offset = m_server.GetTimezoneOffset(); 881 if (offset && entry.has_time()) 882 { 883 // Apply timezone offset 884 wxTimeSpan span(0, offset, 0, 0); 885 entry.time.Add(span); 886 } 887 } 923 entry.AdjustTimeToUTC(m_server.GetTimezoneOffset()); 888 924 889 925 m_entryList.push_back(entry); 890 926 … … 1010 1046 } 1011 1047 } 1012 1048 1013 if (entry.has_time()) 1014 entry.time.Add(m_timezoneOffset); 1049 entry.AdjustTimeToUTC(m_timezoneOffset); 1015 1050 1016 1051 return true; 1017 1052 } … … 1480 1515 entry.ownerGroup = _T(""); 1481 1516 entry.permissions = _T(""); 1482 1517 1483 if (entry.has_time()) 1484 entry.time.Add(m_timezoneOffset); 1518 entry.AdjustTimeToUTC(m_timezoneOffset); 1485 1519 1486 1520 return true; 1487 1521 } … … 1550 1584 return true; 1551 1585 } 1552 1586 1587 bool CDirectoryListingParser::ParseAsFilezillaAttributes(CLine *pLine, CDirentry &entry, bool ignoreBadPermissions) 1588 { 1589 int index = 0; 1590 CToken token; 1591 1592 bool begin = false; 1593 while (1) { 1594 wxString s; 1595 if (!pLine->GetToken(index, token)) 1596 return false; 1597 ++index; 1598 1599 s = token.GetString(); 1600 1601 if (s == _T("FZ_ATTR_END")) 1602 break; 1603 1604 if (begin) { 1605 CToken dataToken; 1606 1607 if (!pLine->GetToken(index, dataToken)) 1608 return false; 1609 ++index; 1610 1611 if (s == _T("SIZE")) 1612 { 1613 entry.size = dataToken.GetNumber(CToken::hex); 1614 } 1615 else if (s == _T("UID")) 1616 { 1617 // Cdirentry doesn't have a UID member 1618 } 1619 else if (s == _T("GID")) 1620 { 1621 // Cdirentry doesn't have a GID member 1622 } 1623 else if (s == _T("PERM")) 1624 { 1625 wxString permissions; 1626 wxLongLong perms = dataToken.GetNumber(CToken::hex); 1627 1628 bool isDir = 0 != (perms & 0040000); 1629 1630 permissions += isDir ? 'd' : '-'; 1631 if (!ignoreBadPermissions && 1632 (isDir != 1633 (0 != (entry.flags & CDirentry::flag_dir)))) 1634 { 1635 // BUGBUG: log error? 1636 return false; 1637 } 1638 1639 const wxString rwx = _("rwxrwxrwx"); 1640 const int len = rwx.length(); 1641 1642 for (int i = 0; i < len; ++i) { 1643 if ( 0 != (perms & (1 << (len - 1 - i))) ) { 1644 permissions += rwx[i]; 1645 } else { 1646 permissions += '-'; 1647 } 1648 } 1649 1650 // setuid 1651 if (0 != (perms & 04000)) 1652 { 1653 permissions[3] = (permissions[3] == '-') ? 'S' : 's'; 1654 } 1655 1656 // setgid 1657 if (0 != (perms & 02000)) 1658 { 1659 permissions[6] = (permissions[6] == '-') ? 'S' : 's'; 1660 } 1661 1662 // sticky bit 1663 if (0 != (perms & 01000)) 1664 { 1665 permissions[9] = (permissions[9] == '-') ? 'T' : 't'; 1666 } 1667 1668 if (entry.permissions != permissions && !ignoreBadPermissions) { 1669 // BUGBUG: log error? 1670 return false; 1671 } 1672 } 1673 else if (s == _T("ATIME")) 1674 { 1675 // Cdirentry doesn't have an ATIME member 1676 } 1677 else if (s == _T("MTIME")) 1678 { 1679 wxLongLong number = dataToken.GetNumber(CToken::hex); 1680 1681 entry.time = wxDateTime((time_t)number.GetValue()); 1682 1683 entry.flags |= CDirentry::flag_timestamp_utc 1684 | CDirentry::flag_timestamp_date 1685 | CDirentry::flag_timestamp_time 1686 | CDirentry::flag_timestamp_seconds; 1687 1688 } 1689 else if (s == _T("CTIME")) 1690 { 1691 // Cdirentry doesn't have an CTIME member 1692 } 1693 else 1694 { 1695 return false; 1696 } 1697 } 1698 else if (s == _T("FZ_ATTR_BEGIN")) 1699 { 1700 begin = true; 1701 continue; 1702 } 1703 } 1704 return true; 1705 } 1706 1553 1707 bool CDirectoryListingParser::ParseAsEplf(CLine *pLine, CDirentry &entry) 1554 1708 { 1555 1709 CToken token; … … 1786 1940 } 1787 1941 } 1788 1942 1789 if (entry.has_time()) 1790 entry.time.Add(m_timezoneOffset); 1943 entry.AdjustTimeToUTC(m_timezoneOffset); 1791 1944 1792 1945 return true; 1793 1946 } … … 1839 1992 entry.flags |= CDirentry::flag_dir; 1840 1993 } 1841 1994 1842 if (entry.has_time()) 1843 entry.time.Add(m_timezoneOffset); 1995 entry.AdjustTimeToUTC(m_timezoneOffset); 1844 1996 1845 1997 return true; 1846 1998 } … … 2016 2168 entry.ownerGroup = _T(""); 2017 2169 entry.permissions = _T(""); 2018 2170 2019 if (entry.has_time()) 2020 entry.time.Add(m_timezoneOffset); 2171 entry.AdjustTimeToUTC(m_timezoneOffset); 2021 2172 } 2022 2173 2023 2174 return true; … … 2246 2397 entry.ownerGroup = _T(""); 2247 2398 entry.permissions = _T(""); 2248 2399 2249 if (entry.has_time()) 2250 entry.time.Add(m_timezoneOffset); 2400 entry.AdjustTimeToUTC(m_timezoneOffset); 2251 2401 2252 2402 return true; 2253 2403 } … … 2412 2562 entry.ownerGroup = _T(""); 2413 2563 entry.permissions = _T(""); 2414 2564 2415 if (entry.has_time()) 2416 entry.time.Add(m_timezoneOffset); 2417 2565 entry.AdjustTimeToUTC(m_timezoneOffset); 2566 2418 2567 return true; 2419 2568 } 2420 2569 … … 2925 3074 entry.permissions = _T(""); 2926 3075 entry.target = _T(""); 2927 3076 2928 if (entry.has_time()) 2929 entry.time.Add(m_timezoneOffset); 2930 3077 entry.AdjustTimeToUTC(m_timezoneOffset); 3078 2931 3079 return true; 2932 3080 } 2933 3081 -
src/putty/psftp.c
7 7 #include <stdarg.h> 8 8 #include <assert.h> 9 9 #include <limits.h> 10 #include <inttypes.h> 10 11 11 12 #ifndef _WINDOWS 12 13 #include <locale.h> … … 1153 1154 * List a directory. If no arguments are given, list pwd; otherwise 1154 1155 * list the directory given in words[1]. 1155 1156 */ 1156 int sftp_cmd_ls (struct sftp_command *cmd)1157 int sftp_cmd_ls_ex(struct sftp_command *cmd, int extrainfo) 1157 1158 { 1158 1159 struct fxp_handle *dirh; 1159 1160 struct fxp_names *names; … … 1265 1266 * And print them. 1266 1267 */ 1267 1268 for (i = 0; i < nnames; i++) { 1269 struct fxp_attrs *attrs = &ournames[i]->attrs; 1268 1270 fzprintf(sftpListentry, "%s", ournames[i]->longname); 1271 1272 if (extrainfo) { 1273 fzprintf_raw(sftpListentry, "FZ_ATTR_BEGIN"); 1274 if (attrs->flags & SSH_FILEXFER_ATTR_SIZE) { 1275 printf(" SIZE %08l" PRIx32 "%08l" PRIx32, attrs->size.hi, attrs->size.lo); 1276 } 1277 if (attrs->flags & SSH_FILEXFER_ATTR_UIDGID) { 1278 printf(" UID %08l" PRIx32, attrs->uid); 1279 printf(" GID %08l" PRIx32, attrs->gid); 1280 } 1281 if (attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) { 1282 printf(" PERM %08l" PRIx32, attrs->permissions); 1283 } 1284 /*FZ: Does not work 1285 if (attrs->flags & (SSH_FILEXFER_ATTR_CREATETIME | SSH_FILEXFER_ATTR_MODIFICATIONTIME)) { 1286 if (attrs->flags & SSH_FILEXFER_ATTR_ACCESSTIME) { 1287 printf(" ATIME %08l" PRIx32 "%08l" PRIx32, attrs->atime.hi, attrs->atime.lo); 1288 } 1289 if (attrs->flags & SSH_FILEXFER_ATTR_CREATETIME) { 1290 printf(" CTIME %08l" PRIx32 "%08l" PRIx32, attrs->ctime.hi, attrs->ctime.lo); 1291 } 1292 if (attrs->flags & SSH_FILEXFER_ATTR_MODIFICATIONTIME) { 1293 printf(" MTIME %08l" PRIx32 "%08l" PRIx32, attrs->mtime.hi, attrs->mtime.lo); 1294 } 1295 } 1296 else 1297 */ 1298 if (attrs->flags & SSH_FILEXFER_ATTR_ACMODTIME) { 1299 printf(" ATIME %08l" PRIx32 "%08l" PRIx32, attrs->atime.hi, attrs->atime.lo); 1300 printf(" MTIME %08l" PRIx32 "%08l" PRIx32, attrs->mtime.hi, attrs->mtime.lo); 1301 printf(" CTIME %08l" PRIx32 "%08l" PRIx32, 0L, 0L); 1302 } 1303 printf(" FZ_ATTR_END\n"); 1304 fflush(stdout); 1305 } 1306 1269 1307 fxp_free_name(ournames[i]); 1270 1308 } 1271 1309 sfree(ournames); … … 1280 1318 1281 1319 return 1; 1282 1320 } 1321 int sftp_cmd_lsfz(struct sftp_command *cmd) 1322 { 1323 return sftp_cmd_ls_ex (cmd, 1); 1324 } 1325 int sftp_cmd_ls(struct sftp_command *cmd) 1326 { 1327 return sftp_cmd_ls_ex (cmd, 0); 1328 } 1283 1329 1284 1330 /* 1285 1331 * Change directories. We do this by canonifying the new name, then … … 2350 2396 sftp_cmd_ls 2351 2397 }, 2352 2398 { 2399 "dir-fz", TRUE, "list remote files", 2400 " [ <directory-name> ]/[ <wildcard> ]\n" 2401 " List the contents of a specified directory on the server.\n" 2402 " If <directory-name> is not given, the current working directory\n" 2403 " is assumed.\n" 2404 " If <wildcard> is given, it is treated as a set of files to\n" 2405 " list; otherwise, all files are listed.\n" 2406 " Special attribute information for each file is returned on\n" 2407 " a second line for each file\n", 2408 sftp_cmd_lsfz 2409 }, 2410 { 2353 2411 "exit", TRUE, "bye", NULL, sftp_cmd_quit 2354 2412 }, 2355 2413 { … … 2398 2456 sftp_cmd_ls 2399 2457 }, 2400 2458 { 2459 "ls-fz", TRUE, "dir-fz", NULL, 2460 sftp_cmd_lsfz 2461 }, 2462 { 2401 2463 "mget", TRUE, "download multiple files at once", 2402 2464 " [ -r ] [ -- ] <filename-or-wildcard> [ <filename-or-wildcard>... ]\n" 2403 2465 " Downloads many files from the server, storing each one under\n"