Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49f0aa41 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Fix windows unicode path issues"

parents bfcff7be efeb7af1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -92,7 +92,9 @@ cc_library_host_static {
        "flatten/XmlFlattener.cpp",
        "io/BigBufferStreams.cpp",
        "io/File.cpp",
        "io/FileInputStream.cpp",
        "io/FileSystem.cpp",
        "io/StringInputStream.cpp",
        "io/Util.cpp",
        "io/ZipArchive.cpp",
        "link/AutoVersioner.cpp",
@@ -164,6 +166,7 @@ cc_library_host_shared {
cc_test_host {
    name: "aapt2_tests",
    srcs: [
        "test/Builders.cpp",
        "test/Common.cpp",
        "**/*_test.cpp",
    ],
+35 −3
Original line number Diff line number Diff line
@@ -14,9 +14,17 @@
 * limitations under the License.
 */

#ifdef _WIN32
// clang-format off
#include <windows.h>
#include <shellapi.h>
// clang-format on
#endif

#include <iostream>
#include <vector>

#include "android-base/utf8.h"
#include "androidfw/StringPiece.h"

#include "Diagnostics.h"
@@ -43,7 +51,7 @@ extern int Optimize(const std::vector<android::StringPiece>& args);

}  // namespace aapt

int main(int argc, char** argv) {
int MainImpl(int argc, char** argv) {
  if (argc >= 2) {
    argv += 1;
    argc -= 1;
@@ -74,7 +82,31 @@ int main(int argc, char** argv) {
    std::cerr << "no command specified\n";
  }

  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..."
            << std::endl;
  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..." << std::endl;
  return 1;
}

int main(int argc, char** argv) {
#ifdef _WIN32
  LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  CHECK(wide_argv != nullptr) << "invalid command line parameters passed to process";

  std::vector<std::string> utf8_args;
  for (int i = 0; i < argc; i++) {
    std::string utf8_arg;
    if (!::android::base::WideToUTF8(wide_argv[i], &utf8_arg)) {
      std::cerr << "error converting input arguments to UTF-8" << std::endl;
      return 1;
    }
    utf8_args.push_back(std::move(utf8_arg));
  }
  LocalFree(wide_argv);

  std::unique_ptr<char* []> utf8_argv(new char*[utf8_args.size()]);
  for (int i = 0; i < argc; i++) {
    utf8_argv[i] = const_cast<char*>(utf8_args[i].c_str());
  }
  argv = utf8_argv.get();
#endif
  return MainImpl(argc, argv);
}
+14 −6
Original line number Diff line number Diff line
@@ -22,9 +22,11 @@
#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "io/StringInputStream.h"
#include "test/Test.h"
#include "xml/XmlPullParser.h"

using ::aapt::io::StringInputStream;
using ::aapt::test::StrValueEq;
using ::aapt::test::ValueEq;
using ::android::ResTable_map;
@@ -43,11 +45,13 @@ constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>

TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
  std::stringstream input(kXmlPreamble);
  input << R"(<attr name="foo"/>)" << std::endl;
  ResourceTable table;
  ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {});
  xml::XmlPullParser xml_parser(input);

  std::string input = kXmlPreamble;
  input += R"(<attr name="foo"/>)";
  StringInputStream in(input);
  xml::XmlPullParser xml_parser(&in);
  ASSERT_FALSE(parser.Parse(&xml_parser));
}

@@ -62,12 +66,16 @@ class ResourceParserTest : public ::testing::Test {
  }

  ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) {
    std::stringstream input(kXmlPreamble);
    input << "<resources>\n" << str << "\n</resources>" << std::endl;
    ResourceParserOptions parserOptions;
    ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config,
                          parserOptions);
    xml::XmlPullParser xmlParser(input);

    std::string input = kXmlPreamble;
    input += "<resources>\n";
    input.append(str.data(), str.size());
    input += "\n</resources>";
    StringInputStream in(input);
    xml::XmlPullParser xmlParser(&in);
    if (parser.Parse(&xmlParser)) {
      return ::testing::AssertionSuccess();
    }
+21 −37
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@

#include <dirent.h>

#include <fstream>
#include <string>

#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/utf8.h"
#include "androidfw/StringPiece.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
@@ -38,6 +38,7 @@
#include "flatten/Archive.h"
#include "flatten/XmlFlattener.h"
#include "io/BigBufferOutputStream.h"
#include "io/FileInputStream.h"
#include "io/Util.h"
#include "proto/ProtoSerialize.h"
#include "util/Files.h"
@@ -46,8 +47,9 @@
#include "xml/XmlDom.h"
#include "xml/XmlPullParser.h"

using android::StringPiece;
using google::protobuf::io::CopyingOutputStreamAdaptor;
using ::aapt::io::FileInputStream;
using ::android::StringPiece;
using ::google::protobuf::io::CopyingOutputStreamAdaptor;

namespace aapt {

@@ -57,19 +59,14 @@ struct ResourcePathData {
  std::string name;
  std::string extension;

  // Original config str. We keep this because when we parse the config, we may
  // add on
  // version qualifiers. We want to preserve the original input so the output is
  // easily
  // Original config str. We keep this because when we parse the config, we may add on
  // version qualifiers. We want to preserve the original input so the output is easily
  // computed before hand.
  std::string config_str;
  ConfigDescription config;
};

/**
 * Resource file paths are expected to look like:
 * [--/res/]type[-config]/name
 */
// Resource file paths are expected to look like: [--/res/]type[-config]/name
static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path,
                                                       std::string* out_error) {
  std::vector<std::string> parts = util::Split(path, file::sDirSep);
@@ -137,9 +134,7 @@ static bool IsHidden(const StringPiece& filename) {
  return util::StartsWith(filename, ".");
}

/**
 * Walks the res directory structure, looking for resource files.
 */
// Walks the res directory structure, looking for resource files.
static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
                                  std::vector<ResourcePathData>* out_path_data) {
  const std::string& root_dir = options.res_dir.value();
@@ -195,22 +190,20 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options,
                         const std::string& output_path) {
  ResourceTable table;
  {
    std::ifstream fin(path_data.source.path, std::ifstream::binary);
    if (!fin) {
    FileInputStream fin(path_data.source.path);
    if (fin.HadError()) {
      context->GetDiagnostics()->Error(DiagMessage(path_data.source)
                                       << "failed to open file: "
                                       << android::base::SystemErrorCodeToString(errno));
                                       << "failed to open file: " << fin.GetError());
      return false;
    }

    // Parse the values file from XML.
    xml::XmlPullParser xml_parser(fin);
    xml::XmlPullParser xml_parser(&fin);

    ResourceParserOptions parser_options;
    parser_options.error_on_positional_arguments = !options.legacy_mode;

    // If the filename includes donottranslate, then the default translatable is
    // false.
    // If the filename includes donottranslate, then the default translatable is false.
    parser_options.translatable = path_data.name.find("donottranslate") == std::string::npos;

    ResourceParser res_parser(context->GetDiagnostics(), &table, path_data.source, path_data.config,
@@ -218,8 +211,6 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options,
    if (!res_parser.Parse(&xml_parser)) {
      return false;
    }

    fin.close();
  }

  if (options.pseudolocalize) {
@@ -239,8 +230,7 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options,
  // Assign an ID to any package that has resources.
  for (auto& pkg : table.packages) {
    if (!pkg->id) {
      // If no package ID was set while parsing (public identifiers), auto
      // assign an ID.
      // If no package ID was set while parsing (public identifiers), auto assign an ID.
      pkg->id = context->GetPackageId();
    }
  }
@@ -367,7 +357,7 @@ static bool FlattenXmlToOutStream(IAaptContext* context, const StringPiece& outp
  return true;
}

static bool IsValidFile(IAaptContext* context, const StringPiece& input_path) {
static bool IsValidFile(IAaptContext* context, const std::string& input_path) {
  const file::FileType file_type = file::GetFileType(input_path);
  if (file_type != file::FileType::kRegular && file_type != file::FileType::kSymlink) {
    if (file_type == file::FileType::kDirectory) {
@@ -393,17 +383,14 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options,

  std::unique_ptr<xml::XmlResource> xmlres;
  {
    std::ifstream fin(path_data.source.path, std::ifstream::binary);
    if (!fin) {
    FileInputStream fin(path_data.source.path);
    if (fin.HadError()) {
      context->GetDiagnostics()->Error(DiagMessage(path_data.source)
                                       << "failed to open file: "
                                       << android::base::SystemErrorCodeToString(errno));
                                       << "failed to open file: " << fin.GetError());
      return false;
    }

    xmlres = xml::Inflate(&fin, context->GetDiagnostics(), path_data.source);

    fin.close();
  }

  if (!xmlres) {
@@ -432,12 +419,9 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options,
    return false;
  }

  // Make sure CopyingOutputStreamAdaptor is deleted before we call
  // writer->FinishEntry().
  // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
  {
    // Wrap our IArchiveWriter with an adaptor that implements the
    // ZeroCopyOutputStream
    // interface.
    // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
    CopyingOutputStreamAdaptor copying_adaptor(writer);
    CompiledFileOutputStream output_stream(&copying_adaptor);

+8 −8
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "flatten/TableFlattener.h"
#include "flatten/XmlFlattener.h"
#include "io/BigBufferInputStream.h"
#include "io/FileInputStream.h"
#include "io/FileSystem.h"
#include "io/Util.h"
#include "io/ZipArchive.h"
@@ -61,8 +62,9 @@
#include "util/Files.h"
#include "xml/XmlDom.h"

using android::StringPiece;
using android::base::StringPrintf;
using ::aapt::io::FileInputStream;
using ::android::StringPiece;
using ::android::base::StringPrintf;

namespace aapt {

@@ -284,13 +286,11 @@ static std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, cons
  return table;
}

/**
 * Inflates an XML file from the source path.
 */
// Inflates an XML file from the source path.
static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
  std::ifstream fin(path, std::ifstream::binary);
  if (!fin) {
    diag->Error(DiagMessage(path) << strerror(errno));
  FileInputStream fin(path);
  if (fin.HadError()) {
    diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
    return {};
  }
  return xml::Inflate(&fin, diag, Source(path));
Loading