Example #1
0
static void SplitGETNameValue(HttpHandler::Arguments& result,
                              const char* start,
                              const char* end)
{
    std::string name, value;

    const char* equal = strchr(start, '=');
    if (equal == NULL || equal >= end)
    {
        name = std::string(start, end - start);
        //value = "";
    }
    else
    {
        name = std::string(start, equal - start);
        value = std::string(equal + 1, end);
    }

    Toolbox::UrlDecode(name);
    Toolbox::UrlDecode(value);

    result.insert(std::make_pair(name, value));
}
Example #2
0
  static void InternalCallback(struct mg_connection *connection,
                               const struct mg_request_info *request)
  {
    MongooseServer* that = reinterpret_cast<MongooseServer*>(request->user_data);
    MongooseOutputStream stream(connection);
    HttpOutput output(stream, that->IsKeepAliveEnabled());

    // Check remote calls
    if (!that->IsRemoteAccessAllowed() &&
        request->remote_ip != LOCALHOST)
    {
      output.SendUnauthorized(ORTHANC_REALM);
      return;
    }


    // Extract the HTTP headers
    HttpHandler::Arguments headers;
    for (int i = 0; i < request->num_headers; i++)
    {
      std::string name = request->http_headers[i].name;
      std::transform(name.begin(), name.end(), name.begin(), ::tolower);
      headers.insert(std::make_pair(name, request->http_headers[i].value));
    }


    // Extract the GET arguments
    HttpHandler::Arguments argumentsGET;
    if (!strcmp(request->request_method, "GET"))
    {
      HttpHandler::ParseGetArguments(argumentsGET, request->query_string);
    }


    // Compute the HTTP method, taking method faking into consideration
    HttpMethod method = HttpMethod_Get;
    if (!ExtractMethod(method, request, headers, argumentsGET))
    {
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }


    // Authenticate this connection
    if (that->IsAuthenticationEnabled() && !IsAccessGranted(*that, headers))
    {
      output.SendUnauthorized(ORTHANC_REALM);
      return;
    }


    // Apply the filter, if it is installed
    const IIncomingHttpRequestFilter *filter = that->GetIncomingHttpRequestFilter();
    if (filter != NULL)
    {
      std::string username = GetAuthenticatedUsername(headers);

      char remoteIp[24];
      sprintf(remoteIp, "%d.%d.%d.%d", 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [3], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [2], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [1], 
              reinterpret_cast<const uint8_t*>(&request->remote_ip) [0]);

      if (!filter->IsAllowed(method, request->uri, remoteIp, username.c_str()))
      {
        output.SendUnauthorized(ORTHANC_REALM);
        return;
      }
    }


    // Extract the body of the request for PUT and POST
    std::string body;
    if (method == HttpMethod_Post ||
        method == HttpMethod_Put)
    {
      PostDataStatus status;

      HttpHandler::Arguments::const_iterator ct = headers.find("content-type");
      if (ct == headers.end())
      {
        // No content-type specified. Assume no multi-part content occurs at this point.
        status = ReadBody(body, connection, headers);          
      }
      else
      {
        std::string contentType = ct->second;
        if (contentType.size() >= multipartLength &&
            !memcmp(contentType.c_str(), multipart, multipartLength))
        {
          status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore());
        }
        else
        {
          status = ReadBody(body, connection, headers);
        }
      }

      switch (status)
      {
        case PostDataStatus_NoLength:
          output.SendStatus(HttpStatus_411_LengthRequired);
          return;

        case PostDataStatus_Failure:
          output.SendStatus(HttpStatus_400_BadRequest);
          return;

        case PostDataStatus_Pending:
          output.SendBody();
          return;

        default:
          break;
      }
    }


    // Decompose the URI into its components
    UriComponents uri;
    try
    {
      Toolbox::SplitUriComponents(uri, request->uri);
    }
    catch (OrthancException)
    {
      output.SendStatus(HttpStatus_400_BadRequest);
      return;
    }


    // Loop over the candidate handlers for this URI
    LOG(INFO) << EnumerationToString(method) << " " << Toolbox::FlattenUri(uri);
    bool found = false;

    for (MongooseServer::Handlers::const_iterator it = 
           that->GetHandlers().begin(); it != that->GetHandlers().end() && !found; ++it) 
    {
      try
      {
        found = (*it)->Handle(output, method, uri, headers, argumentsGET, body);
      }
      catch (OrthancException& e)
      {
        // Using this candidate handler results in an exception
        LOG(ERROR) << "Exception in the HTTP handler: " << e.What();

        switch (e.GetErrorCode())
        {
          case ErrorCode_InexistentFile:
          case ErrorCode_InexistentItem:
          case ErrorCode_UnknownResource:
            output.SendStatus(HttpStatus_404_NotFound);
            break;

          case ErrorCode_BadRequest:
          case ErrorCode_UriSyntax:
            output.SendStatus(HttpStatus_400_BadRequest);
            break;

          default:
            output.SendStatus(HttpStatus_500_InternalServerError);
        }

        return;
      }
      catch (boost::bad_lexical_cast&)
      {
        LOG(ERROR) << "Exception in the HTTP handler: Bad lexical cast";
        output.SendStatus(HttpStatus_400_BadRequest);
        return;
      }
      catch (std::runtime_error&)
      {
        LOG(ERROR) << "Exception in the HTTP handler: Presumably a bad JSON request";
        output.SendStatus(HttpStatus_400_BadRequest);
        return;
      }
    }

    if (!found)
    {
      output.SendStatus(HttpStatus_404_NotFound);
    }
  }