Example #1
0
YETI_Result HttpHeaders::parse(BufferedInputStream & stream)
{
    String header_name;
    String header_value;
    bool   header_pending = false;
    String line;

    while (YETI_SUCCEEDED(stream.read_line(line, YETI_HTTP_PROTOCOL_MAX_LINE_LENGTH))) {
        if (line.get_length() == 0) {
            // end of headers
            break;
        }
        if (header_pending && (line[0] == ' ' || line[0] == '\t')) {
            header_value.append(line.get_chars() + 1, line.get_length() - 1);
        } else {
            if (header_pending) {
                header_value.trim();
                add_header(header_name, header_value);
                header_pending = false;
                YETI_LOG_FINEST_2("header - %s: %s", header_name.get_chars(), header_value.get_chars());
            }

            int colon_index = line.find(':');
            if (colon_index < 1) {
                // invalid syntax, ignore
                continue;
            }
            header_name = line.left(colon_index);
            const char * value = line.get_chars() + colon_index + 1;
            while (*value == ' ' || *value == '\t') {
                value++;
            }
            header_value =  value;
            header_pending = true;
        }
    }

    if (header_pending) {
        header_value.trim();
        add_header(header_name, header_value);
        YETI_LOG_FINEST_2("header - %s: %s", header_name.get_chars(), header_value.get_chars());
    }

    return YETI_SUCCESS;
}
Example #2
0
YETI_Result HttpResponse::parse(BufferedInputStream & stream,
                                HttpResponse *& response)
{
    response = NULL;
    String line;
    YETI_CHECK_FINE(stream.read_line(line, YETI_HTTP_PROTOCOL_MAX_LINE_LENGTH));
    /*if (YETI_FAILED(res)) {
    if (res != YETI_ERROR_TIMEOUT && res != YETI_ERROR_EOS) YETI_CHECK_WARNING(res);
    return res;
    }*/

    YETI_LOG_FINE_1("http response: %s", line.get_chars());

    int first_space = line.find(' ');
    if (first_space < 1) return YETI_ERROR_HTTP_INVALID_RESPONSE_LINE;
    int second_space =  line.find(' ', first_space + 1);
    if (second_space < 0) {
        if (line.get_length() != 12) {
            return YETI_ERROR_HTTP_INVALID_RESPONSE_LINE;
        }
    } else if (second_space != 4) {
        return YETI_ERROR_HTTP_INVALID_RESPONSE_LINE;
    }

    String protocol = line.sub_string(0, first_space);
    String status_code = line.sub_string(first_space + 1, 3);
    String reason_phrase = line.sub_string(first_space + 1 + 3 + 1,
        line.get_length() - (first_space + 1 + 3 + 1));

    YETI_UInt32 status_code_int = 0;
    status_code.to_integer32(status_code_int);
    response = new HttpResponse(status_code_int, reason_phrase, protocol);

    YETI_Result result = response->parse_headers(stream);
    if (YETI_FAILED(result)) {
        delete response;
        response = NULL;
    }

    return result;
}
Example #3
0
void HttpEnvProxySelector::_parse_proxy_env(const String & env, HttpProxyAddress & proxy)
{
    if (env.get_length() == 0) return;
    String proxy_spec;
    if (env.find("://") >= 0) {
        proxy_spec = env;
    } else {
        proxy_spec = "http://" + env;
    }
    Url url(proxy_spec);
    proxy.set_hostname(url.get_host());
    proxy.set_port(url.get_port());
}
/*!

\ingroup Foundation
\brief Converts an XML file to a config context tree.
\details Defined in dmzFoundationXMLUtil.h.
\param[in] FileName String containing name of XML file to parse.
\param[out] data Config object to store parsed XML data.
\param[in] log Pointer to Log for streaming log messages.
\return Returns dmz::True if the XML file was successfully parsed.
\sa dmz::Config \n dmz::ConfigContext

*/
dmz::Boolean
dmz::xml_to_config (const String &FileName, Config &data, Log *log) {

   if (!data) { Config tmp ("global"); data = tmp; }

   ParserXML parser;
   InterpreterXMLConfig interpreter (data);
   parser.set_interpreter (&interpreter);
   Boolean error (False);

   FILE *file = open_file (FileName, "rb");

   if (file) {

      String buffer;

      while (read_file (file, 1024, buffer) && !error) {

         const Int32 Length = buffer.get_length ();
         const char *cbuf = buffer.get_buffer ();

         if (!parser.parse_buffer (cbuf, Length, Length < 1024)) {

            error = True;

            if (log) {

               log->error << "In file: " << FileName << " : " << parser.get_error ()
                  << endl;
            }
         }
      }

      close_file (file);
   }
   else {

      error = True;

      if (log) {

         log->error << "Unable to open file: " << FileName << endl;
      }
   }

   return !error;
}
/*!

\ingroup Foundation
\brief Converts an XML String to a config context tree.
\details Defined in dmzFoundationXMLUtil.h.
\param[in] Value String containing the XML  to parse.
\param[out] data Config object to store parsed XML data.
\param[in] log Pointer to Log for streaming log messages.
\return Returns dmz::True if the XML was successfully parsed.
\sa dmz::Config \n dmz::ConfigContext

*/
dmz::Boolean
dmz::xml_string_to_config (const String &Value, Config &data, Log *log) {

   ParserXML parser;
   InterpreterXMLConfig interpreter (data);
   parser.set_interpreter (&interpreter);
   Boolean error (False);

   if (!parser.parse_buffer (Value.get_buffer (), Value.get_length (), True)) {

      error = True;

      if (log) {

         log->error << "Error parsing: " << endl << "\t"
            << Value << endl << "\t" << parser.get_error () << endl;
      }
   }

   return !error;
}
Example #6
0
/*!

\ingroup Runtime
\brief Remove last element from a scoped Config name.
\details If the String "dmz.type.value" was passed in as \a Name. The string "value"
would be returned in \a value and the string "dmz.type" would be returned in \a remainder.
\param[in] Name String containing scoped config context name.
\param[out] value String for storing the last element of the config context name.
\param[out] remainder String for storing the remaining part of the config context name.
\return Returns dmz::True if the \a Name was successfully separated.

*/
dmz::Boolean
dmz::pop_last_config_scope_element (
    const String Name,
    String &value,
    String &remainder) {

    Boolean result (False);

    const Int32 Length (Name.get_length ());
    Boolean done (False);
    Int32 place = Length - 1;

    while (!done) {

        if (place < 0) {
            done = True;
        }
        else if (Name.get_char (place) == LocalScopeChar) {

            done = True;
        }
        else {
            place--;
        }
    }

    if (place >= 1) {
        value = Name.get_sub (0, place - 1);
    }

    if (place >= 0) {
        remainder = Name.get_sub (place + 1);
        result = True;
    }

    return result;
}
Example #7
0
/*!

\brief Splits a path into the directory, file name, and file extension.
\ingroup System
\details Defined in dmzSystemFile.h.
The \a FullPath is formatted before processing. The file extension is returned with
the leading period. If either a path or extension is not found in the \a FullPath,
the corresponding return value is an empty string.
\param[in] FullPath String containing full path to be split up.
\param[out] path String containing the directory component of the \a FullPath.
\param[out] file String containing the file component of the \a FullPath.
\param[out] ext String containing the extension of the \a FullPath.

*/
void
dmz::split_path_file_ext (
    const String &FullPath,
    String &path,
    String &file,
    String &ext) {

    path = format_path (FullPath);
    file.flush ();
    ext.flush ();

    const Int32 Length = path.get_length ();

    Int32 slashFound = -1;
    Int32 index = Length - 1;

    Boolean done (False);

    while (!done) {

        if (path.get_char (index) == '/') {
            slashFound = index;
            done = True;
        }
        else {
            index--;
            if (index < 0) {
                done = True;
            }
        }
    }

    if (slashFound >= 0) {

        file = path.get_sub (slashFound + 1);
        path = path.get_sub (0, slashFound);
    }
    else {

        file = path;
        path.flush ();
    }

    if (file) {

        const Int32 FileLength = file.get_length ();
        Int32 dotFound = -1;

        index = FileLength - 1;
        done = False;

        while (!done) {

            if (file.get_char (index) == '.') {
                dotFound = index;
                done = True;
            }
            else {
                index--;
                if (index < 0) {
                    done = True;
                }
            }
        }

        if (dotFound > 0) {

            ext = file.get_sub (dotFound);
            file = file.get_sub (0, dotFound - 1);
        }
    }
}
Example #8
0
YETI_Result File::save(const char * path, String & data)
{
    DataBuffer buffer(data.get_chars(), data.get_length());
    return File::save(path, buffer);
}
Example #9
0
YETI_Result HttpRequest::parse(BufferedInputStream & stream,
                               const SocketAddress * endpoint,
                               HttpRequest *& request)
{
    // default return value
    request = NULL;
skip_first_empty_line:
    // read the request line
    String line;
    YETI_CHECK_FINER(stream.read_line(line, YETI_HTTP_PROTOCOL_MAX_LINE_LENGTH));
    YETI_LOG_FINEST_1("http request: %s", line.get_chars());
    // when using keep-alive connections, clients such as XBox 360
    // incorrectly send a few empty lines as body for GET requests
    // so we try to skip them until we find something to parse
    if (line.get_length() == 0) goto skip_first_empty_line;
    if (line.get_length() == 0) goto skip_first_empty_line;

    // check the request line
    int first_space = line.find(' ');
    if (first_space < 0) {
        YETI_LOG_FINE_1("http request: %s", line.get_chars());
        return YETI_ERROR_HTTP_INVALID_REQUEST_LINE;
    }
    int second_space = line.find(' ', first_space + 1);
    if (second_space < 0) {
        YETI_LOG_FINE_1("http request: %s", line.get_chars());
        return YETI_ERROR_HTTP_INVALID_REQUEST_LINE;
    }

    // parse the request line
    String method = line.sub_string(0, first_space);
    String uri = line.sub_string(first_space + 1, second_space - first_space - 1);
    String protocol = line.sub_string(second_space + 1);

    // create a request
    bool proxy_style_request = false;
    if (uri.starts_with("http://", true)) {
        // proxy-style request with absolute URI
        request = new HttpRequest(uri, method, protocol);
        proxy_style_request = true;
    } else {
        // normal absolute path request
        request = new HttpRequest("http:", method, protocol);
    }

    // parse headers
    YETI_Result result = request->parse_headers(stream);
    if (YETI_FAILED(result)) {
        delete request;
        request = NULL;
        return result;
    }

    // update the URL
    if (!proxy_style_request) {
        request->m_url_.set_scheme("http");
        request->m_url_.parse_pathplus(uri);
        request->m_url_.set_port(YETI_HTTP_DEFAULT_PORT);

        // check for a Host: header
        HttpHeader * host_header = request->get_headers().get_header(YETI_HTTP_HEADER_HOST);
        if (host_header) {
            request->m_url_.set_host(host_header->get_value());
            // host sometimes doesn't contain port
            if (endpoint) {
                request->m_url_.set_port(endpoint->get_port());
            }
        } else {
            // use the endpoint as the host
            if (endpoint) {
                request->m_url_.set_host(endpoint->to_string());
            } else {
                // use defaults
                request->m_url_.set_host("localhost");
            }
        }
    }

    return YETI_SUCCESS;
}
Example #10
0
YETI_Result HttpEntity::set_input_stream(const String & string)
{
    MemoryStream * memory_stream = new MemoryStream((const void *)string.get_chars(), string.get_length());
    InputStreamReference body(memory_stream);
    return set_input_stream(body, true);
}