| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/directory_listing.h" |
| |
| #include "base/byte_count.h" |
| #include "base/i18n/time_formatting.h" |
| #include "base/json/string_escape.h" |
| #include "base/logging.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/strings/escape.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/string_view_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "net/base/net_module.h" |
| #include "net/grit/net_resources.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| constexpr auto kByteStringsUnlocalized = std::to_array<const char*>({ |
| " B", |
| " kB", |
| " MB", |
| " GB", |
| " TB", |
| " PB", |
| }); |
| |
| std::string GetSizeString(base::ByteCount bytes) { |
| double unit_amount = bytes.InBytesF(); |
| size_t dimension = 0; |
| constexpr int kKilo = 1024; |
| while (unit_amount >= kKilo && |
| dimension < std::size(kByteStringsUnlocalized) - 1) { |
| unit_amount /= kKilo; |
| dimension++; |
| } |
| |
| if (!bytes.is_zero() && dimension > 0 && unit_amount < 100) { |
| return base::StrCat({base::NumberToStringWithFixedPrecision(unit_amount, 1), |
| kByteStringsUnlocalized[dimension]}); |
| } else { |
| return base::StrCat({base::NumberToStringWithFixedPrecision(unit_amount, 0), |
| kByteStringsUnlocalized[dimension]}); |
| } |
| } |
| |
| } // namespace |
| |
| std::string GetDirectoryListingHeader(const std::u16string& title) { |
| scoped_refptr<base::RefCountedMemory> header( |
| NetModule::GetResource(IDR_DIR_HEADER_HTML)); |
| // This can be null in unit tests. |
| DLOG_IF(WARNING, !header) << "Missing resource: directory listing header"; |
| |
| std::string result; |
| if (header) { |
| result = base::as_string_view(*header); |
| } |
| |
| result.append("<script>start("); |
| base::EscapeJSONString(title, true, &result); |
| result.append(");</script>\n"); |
| |
| return result; |
| } |
| |
| std::string GetDirectoryListingEntry(const std::u16string& name, |
| const std::string& raw_bytes, |
| bool is_dir, |
| base::ByteCount size, |
| base::Time modified) { |
| std::string result; |
| result.append("<script>addRow("); |
| base::EscapeJSONString(name, true, &result); |
| result.append(","); |
| if (raw_bytes.empty()) { |
| base::EscapeJSONString(base::EscapePath(base::UTF16ToUTF8(name)), true, |
| &result); |
| } else { |
| base::EscapeJSONString(base::EscapePath(raw_bytes), true, &result); |
| } |
| |
| if (is_dir) { |
| result.append(",1,"); |
| } else { |
| result.append(",0,"); |
| } |
| |
| // Negative size means unknown or not applicable (e.g. directory). |
| result.append(base::NumberToString(size.InBytes())); |
| result.append(","); |
| |
| std::string size_string; |
| if (size >= base::ByteCount(0)) { |
| size_string = GetSizeString(size); |
| } |
| base::EscapeJSONString(size_string, /*put_in_quotes=*/true, &result); |
| result.append(","); |
| |
| // |modified| can be NULL in FTP listings. |
| std::u16string modified_str; |
| if (modified.is_null()) { |
| result.append("0,"); |
| } else { |
| std::stringstream raw_time_string_stream; |
| // Certain access paths can only get up to seconds resolution, so here we |
| // output the raw time value in seconds for consistency. |
| result.append(base::NumberToString(modified.InMillisecondsSinceUnixEpoch() / |
| base::Time::kMillisecondsPerSecond)); |
| result.append(","); |
| |
| modified_str = base::TimeFormatShortDateAndTime(modified); |
| } |
| |
| base::EscapeJSONString(modified_str, /*put_in_quotes=*/true, &result); |
| result.append(");</script>\n"); |
| |
| return result; |
| } |
| |
| std::string GetParentDirectoryLink() { |
| return std::string("<script>onHasParentDirectory();</script>\n"); |
| } |
| |
| std::string GetSizeStringForTesting(base::ByteCount size) { |
| return GetSizeString(size); |
| } |
| |
| } // namespace net |