Exemple #1
0
  bool Toolbox::IsChildUri(const UriComponents& baseUri,
                           const UriComponents& testedUri)
  {
    if (testedUri.size() < baseUri.size())
    {
      return false;
    }

    for (size_t i = 0; i < baseUri.size(); i++)
    {
      if (baseUri[i] != testedUri[i])
        return false;
    }

    return true;
  }
  static void OutputDirectoryContent(HttpOutput& output,
                                     const IHttpHandler::Arguments& headers,
                                     const UriComponents& uri,
                                     const boost::filesystem::path& p)
  {
    namespace fs = boost::filesystem;

    std::string s;
    s += "<html>";
    s += "  <body>";
    s += "    <h1>Subdirectories</h1>";
    s += "    <ul>";

    if (uri.size() > 0)
    {
      std::string h = Toolbox::FlattenUri(uri) + "/..";
      s += "<li><a href=\"" + h + "\">..</a></li>";
    }

    fs::directory_iterator end;
    for (fs::directory_iterator it(p) ; it != end; ++it)
    {
#if BOOST_HAS_FILESYSTEM_V3 == 1
      std::string f = it->path().filename().string();
#else
      std::string f = it->path().filename();
#endif

      std::string h = Toolbox::FlattenUri(uri) + "/" + f;
      if (fs::is_directory(it->status()))
        s += "<li><a href=\"" + h + "\">" + f + "</a></li>";
    }      

    s += "    </ul>";      
    s += "    <h1>Files</h1>";
    s += "    <ul>";

    for (fs::directory_iterator it(p) ; it != end; ++it)
    {
#if BOOST_HAS_FILESYSTEM_V3 == 1
      std::string f = it->path().filename().string();
#else
      std::string f = it->path().filename();
#endif

      std::string h = Toolbox::FlattenUri(uri) + "/" + f;
      if (SystemToolbox::IsRegularFile(it->path().string()))
      {
        s += "<li><a href=\"" + h + "\">" + f + "</a></li>";
      }
    }      

    s += "    </ul>";
    s += "  </body>";
    s += "</html>";

    output.SetContentType("text/html");
    output.Answer(s);
  }
Exemple #3
0
  void Toolbox::SplitUriComponents(UriComponents& components,
                                   const std::string& uri)
  {
    static const char URI_SEPARATOR = '/';

    components.clear();

    if (uri.size() == 0 ||
        uri[0] != URI_SEPARATOR)
    {
      throw OrthancException(ErrorCode_UriSyntax);
    }

    // Count the number of slashes in the URI to make an assumption
    // about the number of components in the URI
    unsigned int estimatedSize = 0;
    for (unsigned int i = 0; i < uri.size(); i++)
    {
      if (uri[i] == URI_SEPARATOR)
        estimatedSize++;
    }

    components.reserve(estimatedSize - 1);

    unsigned int start = 1;
    unsigned int end = 1;
    while (end < uri.size())
    {
      // This is the loop invariant
      assert(uri[start - 1] == '/' && (end >= start));

      if (uri[end] == '/')
      {
        components.push_back(std::string(&uri[start], end - start));
        end++;
        start = end;
      }
      else
      {
        end++;
      }
    }

    if (start < uri.size())
    {
      components.push_back(std::string(&uri[start], end - start));
    }

    for (size_t i = 0; i < components.size(); i++)
    {
      if (components[i].size() == 0)
      {
        // Empty component, as in: "/coucou//e"
        throw OrthancException(ErrorCode_UriSyntax);
      }
    }
  }
  bool RestApiPath::Match(IHttpHandler::Arguments& components,
                          UriComponents& trailing,
                          const UriComponents& uri) const
  {
    assert(uri_.size() == components_.size());

    if (uri.size() < uri_.size())
    {
      return false;
    }

    if (!hasTrailing_ && uri.size() > uri_.size())
    {
      return false;
    }

    components.clear();
    trailing.clear();

    assert(uri_.size() <= uri.size());
    for (size_t i = 0; i < uri_.size(); i++)
    {
      if (components_[i].size() == 0)
      {
        // This URI component is not a free parameter
        if (uri_[i] != uri[i])
        {
          return false;
        }
      }
      else
      {
        // This URI component is a free parameter
        components[components_[i]] = uri[i];
      }
    }

    if (hasTrailing_)
    {
      trailing.assign(uri.begin() + uri_.size(), uri.end());
    }

    return true;
  }
Exemple #5
0
  std::string Toolbox::FlattenUri(const UriComponents& components,
                                  size_t fromLevel)
  {
    if (components.size() <= fromLevel)
    {
      return "/";
    }
    else
    {
      std::string r;

      for (size_t i = fromLevel; i < components.size(); i++)
      {
        r += "/" + components[i];
      }

      return r;
    }
  }
Exemple #6
0
  void Toolbox::TruncateUri(UriComponents& target,
                            const UriComponents& source,
                            size_t fromLevel)
  {
    target.clear();

    if (source.size() > fromLevel)
    {
      target.resize(source.size() - fromLevel);

      size_t j = 0;
      for (size_t i = fromLevel; i < source.size(); i++, j++)
      {
        target[j] = source[i];
      }

      assert(j == target.size());
    }
  }
Exemple #7
0
TEST(ParseGetQuery, Test2)
{
  UriComponents uri;
  HttpHandler::Arguments a;
  HttpHandler::ParseGetQuery(uri, a, "/instances/test/world");
  ASSERT_EQ(3u, uri.size());
  ASSERT_EQ("instances", uri[0]);
  ASSERT_EQ("test", uri[1]);
  ASSERT_EQ("world", uri[2]);
  ASSERT_EQ(0u, a.size());
}
  bool FilesystemHttpHandler::Handle(
    HttpOutput& output,
    RequestOrigin /*origin*/,
    const char* /*remoteIp*/,
    const char* /*username*/,
    HttpMethod method,
    const UriComponents& uri,
    const Arguments& headers,
    const GetArguments& arguments,
    const char* /*bodyData*/,
    size_t /*bodySize*/)
  {
    if (!Toolbox::IsChildUri(pimpl_->baseUri_, uri))
    {
      // This URI is not served by this handler
      return false;
    }

    if (method != HttpMethod_Get)
    {
      output.SendMethodNotAllowed("GET");
      return true;
    }

    namespace fs = boost::filesystem;

    fs::path p = pimpl_->root_;
    for (size_t i = pimpl_->baseUri_.size(); i < uri.size(); i++)
    {
      p /= uri[i];
    }

    if (fs::exists(p) && fs::is_regular_file(p))
    {
      FilesystemHttpSender sender(p);
      output.Answer(sender);   // TODO COMPRESSION
    }
    else if (listDirectoryContent_ &&
             fs::exists(p) && 
             fs::is_directory(p))
    {
      OutputDirectoryContent(output, headers, uri, p);
    }
    else
    {
      output.SendStatus(HttpStatus_404_NotFound);
    }

    return true;
  } 
Exemple #9
0
TEST(ParseGetQuery, Test1)
{
  UriComponents uri;
  HttpHandler::Arguments a;
  HttpHandler::ParseGetQuery(uri, a, "/instances/test/world?aaa=baaa&bb=a&aa=c");
  ASSERT_EQ(3u, uri.size());
  ASSERT_EQ("instances", uri[0]);
  ASSERT_EQ("test", uri[1]);
  ASSERT_EQ("world", uri[2]);
  ASSERT_EQ(3u, a.size());
  ASSERT_EQ(a["aaa"], "baaa");
  ASSERT_EQ(a["bb"], "a");
  ASSERT_EQ(a["aa"], "c");
}
TEST(ParseGetQuery, Test2)
{
  UriComponents uri;
  IHttpHandler::GetArguments b;
  HttpToolbox::ParseGetQuery(uri, b, "/instances/test/world");

  IHttpHandler::Arguments a;
  HttpToolbox::CompileGetArguments(a, b);

  ASSERT_EQ(3u, uri.size());
  ASSERT_EQ("instances", uri[0]);
  ASSERT_EQ("test", uri[1]);
  ASSERT_EQ("world", uri[2]);
  ASSERT_EQ(0u, a.size());
}
  bool FilesystemHttpHandler::Handle(
    HttpOutput& output,
    HttpMethod method,
    const UriComponents& uri,
    const Arguments& headers,
    const GetArguments& arguments,
    const std::string&)
  {
    if (!Toolbox::IsChildUri(pimpl_->baseUri_, uri))
    {
      // This URI is not served by this handler
      return false;
    }

    if (method != HttpMethod_Get)
    {
      output.SendMethodNotAllowed("GET");
      return true;
    }

    namespace fs = boost::filesystem;

    fs::path p = pimpl_->root_;
    for (size_t i = pimpl_->baseUri_.size(); i < uri.size(); i++)
    {
      p /= uri[i];
    }

    if (fs::exists(p) && fs::is_regular_file(p))
    {
      FilesystemHttpSender(p).Send(output);

      //output.AnswerFileAutodetectContentType(p.string());
    }
    else if (listDirectoryContent_ &&
             fs::exists(p) && 
             fs::is_directory(p))
    {
      OutputDirectoryContent(output, uri, p);
    }
    else
    {
      output.SendStatus(HttpStatus_404_NotFound);
    }

    return true;
  } 
Exemple #12
0
TEST(Uri, SplitUriComponents)
{
  UriComponents c;
  Toolbox::SplitUriComponents(c, "/cou/hello/world");
  ASSERT_EQ(3u, c.size());
  ASSERT_EQ("cou", c[0]);
  ASSERT_EQ("hello", c[1]);
  ASSERT_EQ("world", c[2]);

  Toolbox::SplitUriComponents(c, "/cou/hello/world/");
  ASSERT_EQ(3u, c.size());
  ASSERT_EQ("cou", c[0]);
  ASSERT_EQ("hello", c[1]);
  ASSERT_EQ("world", c[2]);

  Toolbox::SplitUriComponents(c, "/cou/hello/world/a");
  ASSERT_EQ(4u, c.size());
  ASSERT_EQ("cou", c[0]);
  ASSERT_EQ("hello", c[1]);
  ASSERT_EQ("world", c[2]);
  ASSERT_EQ("a", c[3]);

  Toolbox::SplitUriComponents(c, "/");
  ASSERT_EQ(0u, c.size());

  Toolbox::SplitUriComponents(c, "/hello");
  ASSERT_EQ(1u, c.size());
  ASSERT_EQ("hello", c[0]);

  Toolbox::SplitUriComponents(c, "/hello/");
  ASSERT_EQ(1u, c.size());
  ASSERT_EQ("hello", c[0]);

  ASSERT_THROW(Toolbox::SplitUriComponents(c, ""), OrthancException);
  ASSERT_THROW(Toolbox::SplitUriComponents(c, "a"), OrthancException);
  ASSERT_THROW(Toolbox::SplitUriComponents(c, "/coucou//coucou"), OrthancException);
}
TEST(RestApi, RestApiPath)
{
  IHttpHandler::Arguments args;
  UriComponents trail;

  {
    RestApiPath uri("/coucou/{abc}/d/*");
    ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d/e/f/g"));
    ASSERT_EQ(1u, args.size());
    ASSERT_EQ(3u, trail.size());
    ASSERT_EQ("moi", args["abc"]);
    ASSERT_EQ("e", trail[0]);
    ASSERT_EQ("f", trail[1]);
    ASSERT_EQ("g", trail[2]);

    ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/f"));
    ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d/"));
    ASSERT_FALSE(uri.Match(args, trail, "/a/moi/d"));
    ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi"));

    ASSERT_EQ(3u, uri.GetLevelCount());
    ASSERT_TRUE(uri.IsUniversalTrailing());

    ASSERT_EQ("coucou", uri.GetLevelName(0));
    ASSERT_THROW(uri.GetWildcardName(0), OrthancException);

    ASSERT_EQ("abc", uri.GetWildcardName(1));
    ASSERT_THROW(uri.GetLevelName(1), OrthancException);

    ASSERT_EQ("d", uri.GetLevelName(2));
    ASSERT_THROW(uri.GetWildcardName(2), OrthancException);
  }

  {
    RestApiPath uri("/coucou/{abc}/d");
    ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/d/e/f/g"));
    ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d"));
    ASSERT_EQ(1u, args.size());
    ASSERT_EQ(0u, trail.size());
    ASSERT_EQ("moi", args["abc"]);

    ASSERT_EQ(3u, uri.GetLevelCount());
    ASSERT_FALSE(uri.IsUniversalTrailing());

    ASSERT_EQ("coucou", uri.GetLevelName(0));
    ASSERT_THROW(uri.GetWildcardName(0), OrthancException);

    ASSERT_EQ("abc", uri.GetWildcardName(1));
    ASSERT_THROW(uri.GetLevelName(1), OrthancException);

    ASSERT_EQ("d", uri.GetLevelName(2));
    ASSERT_THROW(uri.GetWildcardName(2), OrthancException);
  }

  {
    RestApiPath uri("/*");
    ASSERT_TRUE(uri.Match(args, trail, "/a/b/c"));
    ASSERT_EQ(0u, args.size());
    ASSERT_EQ(3u, trail.size());
    ASSERT_EQ("a", trail[0]);
    ASSERT_EQ("b", trail[1]);
    ASSERT_EQ("c", trail[2]);

    ASSERT_EQ(0u, uri.GetLevelCount());
    ASSERT_TRUE(uri.IsUniversalTrailing());
  }
}