cpp-netlib-0.11.2-final/000077500000000000000000000000001256751517300147335ustar00rootroot00000000000000cpp-netlib-0.11.2-final/.clang-format000066400000000000000000000022441256751517300173100ustar00rootroot00000000000000BasedOnStyle: Google AccessModifierOffset: -1 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true AlwaysBreakTemplateDeclarations: true AlwaysBreakBeforeMultilineStrings: true BreakBeforeBinaryOperators: false BreakConstructorInitializersBeforeComma: false BinPackParameters: true ColumnLimit: 80 ConstructorInitializerAllOnOneLineOrOnePerLine: true DerivePointerBinding: true ExperimentalAutoDetectBinPacking: false IndentCaseLabels: true MaxEmptyLinesToKeep: 1 ObjCSpaceBeforeProtocolList: false PenaltyBreakComment: 60 PenaltyBreakString: 1000 PenaltyBreakFirstLessLess: 120 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerBindsToType: true SpacesBeforeTrailingComments: 2 Cpp11BracedListStyle: true Standard: Auto IndentWidth: 2 TabWidth: 4 UseTab: false BreakBeforeBraces: Attach IndentFunctionDeclarationAfterType: true SpacesInParentheses: false SpaceInEmptyParentheses: false SpacesInCStyleCastParentheses: false SpaceAfterControlStatementKeyword: true cpp-netlib-0.11.2-final/.gitignore000066400000000000000000000001561256751517300167250ustar00rootroot00000000000000*.cmake *.swp *.pyc CMakeCache.txt CMakeFiles Makefile Testing *.gch libs/mime/test/mime-roundtrip *.a _build cpp-netlib-0.11.2-final/.travis.yml000066400000000000000000000050241256751517300170450ustar00rootroot00000000000000language: - cpp compiler: - gcc - clang env: - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" - BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" - BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" before_install: - if [ "${CXX}" == "g++" ] || [ ${BUILD_SHARED_LIBS} = "OFF" ]; then sudo add-apt-repository ppa:boost-latest/ppa --yes; sudo apt-get update; fi - if [ "${CXX}" == "clang++" ] && [ ${BUILD_SHARED_LIBS} = "ON" ]; then svn export http://svn.boost.org/svn/boost/tags/release/Boost_${BOOST_VER//./_} ../boost_${BOOST_VER//./_}; export BOOST_ROOT=$TRAVIS_BUILD_DIR/../boost_${BOOST_VER//./_}; fi install: - if [ "${CXX}" == "g++" ] || [ ${BUILD_SHARED_LIBS} = "OFF" ]; then sudo apt-get install libboost${BOOST_VER/%.0/}-all-dev; fi - if [ "${CXX}" == "clang++" ] && [ ${BUILD_SHARED_LIBS} = "ON" ]; then cd $BOOST_ROOT; ./bootstrap.sh --with-toolset=$CC; ./b2 -j4 --stagedir=.; cd -; fi script: - cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DCPP-NETLIB_ENABLE_HTTPS=${ENABLE_HTTPS} - make - make test after_failure: - cat Testing/Temporary/LastTest.log cpp-netlib-0.11.2-final/.ycm_extra_conf.py000066400000000000000000000037431256751517300203720ustar00rootroot00000000000000# Copyright 2013 Google, Inc. # Copyright 2013 Dean Michael Berris # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # # Project-wide configuration for YouCompleteMe Vim plugin. # # Based off of Valloric's .ycm_conf_extra.py for YouCompleteMe: # https://github.com/Valloric/YouCompleteMe/blob/master/cpp/ycm/.ycm_extra_conf.py # import os import ycm_core flags = [ '-Wall', '-Wextra', '-Werror', '-std=c++03', '-isystem', '.', '-isystem', '/usr/include', '-isystem', '/usr/include/c++/4.6', '-isystem', '/usr/include/clang/3.0/include', '-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1', '-I', os.environ['BOOST_ROOT'], # Always enable debugging for the project when building for semantic # completion. '-DBOOST_NETWORK_DEBUG', ] def DirectoryOfThisScript(): return os.path.dirname(os.path.abspath(__file__)) def MakeRelativePathsInFlagsAbsolute(flags, working_directory): if not working_directory: return list(flags) new_flags = [] make_next_absolute = False path_flags = ['-isystem', '-I', '-iquote', '--sysroot='] for flag in flags: new_flag = flag if make_next_absolute: make_next_absolute = False if not flag.startswith('/'): new_flag = os.path.join(working_directory, flag) for path_flag in path_flags: if flag == path_flag: make_next_absolute = True break if flag.startswith(path_flag): path = flag[len(path_flag):] new_flag = path_flag + os.path.join(working_directory, path) break if new_flag: new_flags.append(new_flag) return new_flags def FlagsForFile(filename): relative_to = DirectoryOfThisScript() final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) return {'flags': final_flags, 'do_cache': True } cpp-netlib-0.11.2-final/CMakeLists.txt000066400000000000000000000126431256751517300175010ustar00rootroot00000000000000# Copyright (c) Dean Michael Berris 2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) cmake_minimum_required(VERSION 2.8) project(CPP-NETLIB) option( CPP-NETLIB_BUILD_SHARED_LIBS "Build cpp-netlib as shared libraries." OFF ) option( CPP-NETLIB_BUILD_TESTS "Build the cpp-netlib project tests." ON) option( CPP-NETLIB_BUILD_EXPERIMENTS "Build the cpp-netlib project experiments." ON) option( CPP-NETLIB_BUILD_EXAMPLES "Build the cpp-netlib project examples." ON) option( CPP-NETLIB_ENABLE_HTTPS "Build cpp-netlib with support for https if OpenSSL is found." ON) include(GNUInstallDirs) # determine install path for CMake config files if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKE_DIR CMake) else() set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/cppnetlib) endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") # Make relative cmake install path absolute (needed later on) if(NOT IS_ABSOLUTE "${INSTALL_CMAKE_DIR}") set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}") endif() if(CPP-NETLIB_BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) message (STATUS "Linking boost testing libs dynamically...") set(Boost_USE_STATIC_LIBS OFF) set(CPP-NETLIB_BUILD_SHARED_LIBS ON) set(BUILD_SHARED_LIBS ON) add_definitions(-DBOOST_TEST_DYN_LINK) else() set(Boost_USE_STATIC_LIBS ON) set(CPP-NETLIB_BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF) endif() set(Boost_USE_MULTI_THREADED ON) find_package( Boost 1.54.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options chrono atomic ) if (CPP-NETLIB_ENABLE_HTTPS) find_package( OpenSSL ) endif() find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) set(CPPNETLIB_VERSION_MAJOR 0) # MUST bump this whenever we make ABI-incompatible changes set(CPPNETLIB_VERSION_MINOR 11) set(CPPNETLIB_VERSION_PATCH 1) set(CPPNETLIB_VERSION_STRING ${CPPNETLIB_VERSION_MAJOR}.${CPPNETLIB_VERSION_MINOR}.${CPPNETLIB_VERSION_PATCH}) if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() if (OPENSSL_FOUND) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) include_directories(${OPENSSL_INCLUDE_DIR}) endif() if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # We want to link in C++11 mode if we're using Clang and on OS X. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256 -std=c++11 -stdlib=libc++") else() # We just add the -Wall and a high enough template depth # flag for Clang in other systems. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256") endif() endif() if (Boost_FOUND) if (MSVC) add_definitions(-D_SCL_SECURE_NO_WARNINGS) endif(MSVC) if (WIN32) add_definitions(-D_WIN32_WINNT=0x0501) endif(WIN32) include_directories(${Boost_INCLUDE_DIRS}) enable_testing() add_subdirectory(libs/network/src) if (CPP-NETLIB_BUILD_TESTS) add_subdirectory(libs/network/test) endif (CPP-NETLIB_BUILD_TESTS) if (CPP-NETLIB_BUILD_EXPERIMENTS) add_subdirectory(libs/network/experiment) endif (CPP-NETLIB_BUILD_EXPERIMENTS) if (NOT MSVC AND CPP-NETLIB_BUILD_TESTS) add_subdirectory(libs/mime/test) endif(NOT MSVC AND CPP-NETLIB_BUILD_TESTS) if (CPP-NETLIB_BUILD_EXAMPLES) add_subdirectory(libs/network/example) endif (CPP-NETLIB_BUILD_EXAMPLES) endif(Boost_FOUND) if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif() enable_testing() install(DIRECTORY boost DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) ### ## Export Targets # (so cpp-netlib can be easily used by other CMake projects) # [see http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file] # Add all targets to the build-tree export set export(TARGETS cppnetlib-client-connections cppnetlib-server-parsers cppnetlib-uri FILE "${PROJECT_BINARY_DIR}/cppnetlibTargets.cmake") # Export the package for use from the build-tree # (this registers the build-tree with a global CMake-registry) export(PACKAGE cppnetlib) # Create the cppnetlibConfig.cmake and cppnetlibConfigVersion files file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_FULL_INCLUDEDIR}") # ... for the build tree set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" ${Boost_INCLUDE_DIRS}) configure_file(cppnetlibConfig.cmake.in "${PROJECT_BINARY_DIR}/cppnetlibConfig.cmake" @ONLY) # ... for the install tree set(CONF_INCLUDE_DIRS "\${CPPNETLIB_CMAKE_DIR}/${REL_INCLUDE_DIR}") set(CONF_INCLUDE_DIRS ${CONF_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) configure_file(cppnetlibConfig.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cppnetlibConfig.cmake" @ONLY) # ... for both configure_file(cppnetlibConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/cppnetlibConfigVersion.cmake" @ONLY) # Install the cppnetlibConfig.cmake and cppnetlibConfigVersion.cmake install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cppnetlibConfig.cmake" "${PROJECT_BINARY_DIR}/cppnetlibConfigVersion.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) # Install the export set for use with the install-tree install(EXPORT cppnetlibTargets DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) cpp-netlib-0.11.2-final/LICENSE_1_0.txt000066400000000000000000000024721256751517300172220ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cpp-netlib-0.11.2-final/RATIONALE.txt000066400000000000000000000035411256751517300170150ustar00rootroot00000000000000C++ Networking Library Goals and Scope Objectives ---------- o Develop a high quality, portable, easy to use C++ networking library o Enable users to easily extend the library o Lower the barrier to entry for cross-platform network-aware C++ applications Goals ----- * Implement a simple message implementation which can be used in network protocol-specific routines for inter-operability and to provide a generic interface to manipulating network-oriented messages. * Implement easy to use protocol client libraries such as (but not limited to): - HTTP 1.0/1.1 - (E)SMTP - SNMP - ICMP * Implement an easy to embed HTTP server container type that supports most modern HTTP 1.1 features. * Implement an efficient easy to use URI class/parser. * Implement a fully compliant cross-platform asynchronous DNS resolver either as a wrapper to external (C) libraries, or as hand-rolled implementation. * Implement a MIME handler which builds message objects from either data retrieved from the network or other sources and create text/binary representations from existing message objects intended for transport over the network. Scope ----- * The library will provide a generic message class which is intended to be the common message type used by the protocol libraries. * The library will only contain client implementations for the various supported protocols. * The library will use only STL and Boost C++ library components, utilities, and libraries throughout the implementation. * The library will strive to use C++ templates and template metaprogramming techniques in order to not require the building of external shared/static libraries. In other words, the library will be header-only and compliant with the C++ standard. cpp-netlib-0.11.2-final/README.rst000066400000000000000000000134131256751517300164240ustar00rootroot00000000000000C++ Network Library =================== Introduction ------------ cpp-netlib is a collection of network related routines/implementations geared towards providing a robust cross-platform networking library. cpp-netlib offers the following implementations: * Common Message Type -- A generic message type which can be used to encapsulate and store message related information, used by all network implementations as the primary means of data exchange. * Network protocol message parsers -- A collection of parsers which generate message objects from strings. * Adapters and Wrappers -- A collection of Adapters and wrappers aimed towards making the message type STL friendly. * Network protocol client and server implementations -- A collection of network protocol implementations that include embeddable client and server types. This library is released under the Boost Software License (please see http://boost.org/LICENSE_1_0.txt or the accompanying LICENSE_1_0.txt file for the full text. Downloading cpp-netlib ---------------------- You can find official release packages of the library at:: http://github.com/cpp-netlib/cpp-netlib/downloads Building and Installing ----------------------- Building with CMake ~~~~~~~~~~~~~~~~~~~ To build the libraries and run the tests with CMake, you will need to have CMake version 2.8 or higher installed appropriately in your system. :: $ cmake --version cmake version 2.8.1 Inside the cpp-netlib directory, you can issue the following statements to configure and generate the Makefiles, and build the tests:: $ cd ~/cpp-netlib # we're assuming it's where cpp-netlib is $ cmake -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=clang \ > -DCMAKE_CXX_COMPILER=clang++ \ > . Once CMake is done with generating the Makefiles and configuring the project, you can now build the tests and run them:: $ cd ~/cpp-netlib $ make $ make test If for some reason some of the tests fail, you can send the files in ``Testing/Temporary/`` as attachments to the cpp-netlib `developers mailing list`_. .. _`developers mailing list`: cpp-netlib@googlegroups.com Building with Boost.Build ~~~~~~~~~~~~~~~~~~~~~~~~~ If you don't already have Boost.Build set up on your system, follow the steps indicated in the Boost Getting Started Guide [#]_ -- you will particularly want to copy the ``bjam`` executable to a directory that is already in your ``PATH`` so that you don't have to go hunting for it all the time. A good place to put it is in ``/usr/local/bin``. .. [#] http://www.boost.org/doc/libs/release/more/getting_started/ Building and running the tests can be as simple as doing the following:: $ cd ~/cpp-netlib $ bjam Doing this will already build all the tests and run them as they are built. In case you encounter any problems and would like to report it to the developers, please do the following:: $ cd ~/cpp-netlib $ bjam 2>&1 >build-test.log And then attach the ``build-test.log`` file to the email you will send to the cpp-netlib `developers mailing list`_. .. _`developers mailing list`: cpp-netlib@googlegroups.com Running Tests ------------- If you want to run the tests that come with cpp-netlib, there are a few things you will need. These are: * A compiler (GCC 4.x, Clang 2.8, MSVC 2008) * A build tool (CMake [#]_ recommended, Boost.Build also an option) * OpenSSL headers (optional) .. note:: This assumes that you have cpp-netlib at the top-level of your home directory. [#] http://www.cmake.org/ Hacking on cpp-netlib --------------------- cpp-netlib is being developed with the git_ distributed SCM system. cpp-netlib is hosted on GitHub_ following the GitHub recommended practice of forking the repository and submitting pull requests to the source repository. You can read more about the forking_ process and submitting `pull requests`_ if you're not familiar with either process yet. .. _git: http://git-scm.com/ .. _GitHub: http://github.com/ .. _forking: http://help.github.com/forking/ .. _`pull requests`: http://help.github.com/pull-requests/ Because cpp-netlib is released under the `Boost Software License`_ it is recommended that any file you make changes to bear your copyright notice alongside the original authors' copyright notices on the file. Typically the copyright notices are at the top of each file in the project. .. _`Boost Software License`: http://www.boost.org/LICENSE_1_0.txt At the time of writing, there are no coding conventions being followed but if you write in the general style that is already existing in the project that would be greatly appreciated. Copious amounts of comments will be called out, but code that is not self-explanatory typically at least requires a rationale documentation in comments explaining "why" the code is written that way. The main "upstream" repository is the one hosted by the original maintainer of the project (Dean Michael Berris) at http://github.com/mikhailberis/cpp-netlib. The "official" release repository is maintained at http://github.com/cpp-netlib/cpp-netlib -- which is a fork of the upstream repository. It is recommended that forks be made against the upstream repostory and pull requests be submitted against the upstream repository so that patches and other implementations can be curated by the original maintainer. Contact and Support ------------------- In case you have any questions or would like to make feature requests, you can contact the development team through the `developers mailing list`_ or by filing issues at http://github.com/cpp-netlib/cpp-netlib/issues. .. _`developers mailing list`: cpp-netlib@googlegroups.com You can reach the maintainers of the project through:: Dean Michael Berris (dberris@google.com) Glyn Matthews (glyn.matthews@gmail.com) cpp-netlib-0.11.2-final/boost/000077500000000000000000000000001256751517300160615ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/mime.hpp000066400000000000000000000722561256751517300175350ustar00rootroot00000000000000// // Copyright Marshall Clow 2009-2010 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // #ifndef _BOOST_MIME_HPP #define _BOOST_MIME_HPP #include #include #include #include #include #include #include // pulls in all of Phoenix #include #include #include #include #include #include // #define DUMP_MIME_DATA 1 namespace boost { namespace mime { // Errors are reported using this exception class class mime_parsing_error : public std::runtime_error { public: explicit mime_parsing_error(const std::string &msg) : std::runtime_error(msg) {} }; template class basic_mime; namespace detail { static const char *k_crlf = "\015\012"; static const char *k_package_name = "Proposed.Boost.Mime"; static const char *k_package_version = "0.1"; static const char *k_content_type_header = "Content-Type"; static const char *k_mime_version_header = "Mime-Version"; struct default_types { typedef std::string string_type; // typedef std::pair < std::string, string_type > header_type; typedef std::vector body_type; }; template struct find_mime_header { find_mime_header(const char *str) : searchFor(str) {} bool operator()(const std::pair &val) const { return boost::iequals(val.first, searchFor); } private: const char *searchFor; }; #ifdef DUMP_MIME_DATA struct tracer { tracer(const char *fn) : fn_(fn) { std::cout << "->" << fn_ << std::endl; } ~tracer() { std::cout << "<-" << fn_ << std::endl; } const char *fn_; }; #else struct tracer { tracer(const char *) {} ~tracer() {} }; #endif // Parsing a Content-Type header typedef std::pair phrase_t; typedef std::vector phrase_container_t; struct mime_content_type { std::string type; std::string sub_type; phrase_container_t phrases; }; namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; using boost::spirit::_val; using boost::spirit::_1; template struct mime_header_parser : qi::grammar { mime_header_parser() : mime_header_parser::base_type(mime_headerList) { mime_headerList = *(mime_header) >> crlf; mime_header = token >> qi::lit(':') >> value >> crlf; token = qi::char_("a-zA-Z") >> *qi::char_("a-zA-Z_0-9\\-"); // In Classifieds/000001, a header begins with a CRLF value = (valuePart[_val = _1] | qi::eps) >> *(valueCont[_val += "\015\012" + _1]); valueCont = crlf >> contWS[_val += _1] >> valuePart[_val += _1]; valuePart = +qi::char_("\t -~"); contWS = +qi::char_(" \t"); crlf = qi::lit(k_crlf); /* mime_headerList.name("mime-header-list"); mime_header.name ("mime-header"); token.name ("mime-token"); valuePart.name ("mime-value-part"); value.name ("mime-value"); qi::on_error ( mime_headerList, std::cout << phoenix::val("Error! Expecting ") << qi::labels::_4 << phoenix::val(" here: \"") << phoenix::construct(qi::labels::_3, qi::labels::_2) << phoenix::val("\"") << std::endl ); */ } qi::rule mime_headerList; qi::rule mime_header; qi::rule token, value, valueCont, valuePart, contWS; qi::rule crlf; }; template static Container read_headers(Iterator &begin, Iterator end) { tracer t(__func__); Container retVal; mime_header_parser mh_parser; bool b = qi::parse(begin, end, mh_parser, retVal); if (!b) throw mime_parsing_error("Failed to parse headers"); #ifdef DUMP_MIME_DATA std::cout << "******Headers*******" << std::endl; for (typename Container::const_iterator iter = retVal.begin(); iter != retVal.end(); ++iter) { std::string val = iter->second; size_t idx; while (std::string::npos != (idx = val.find(k_crlf))) val.replace(idx, std::strlen(k_crlf), "\n"); std::cout << iter->first << ": " << val << std::endl; } std::cout << std::endl << "******Headers*******" << std::endl; #endif return retVal; } // The structure of a Content-Type mime header is taken from RFC 2045 // http://www.ietf.org/rfc/rfc2045.txt, section 5.1 template struct mime_content_type_parser : qi::grammar { mime_content_type_parser() : mime_content_type_parser::base_type(content_type_header) { content_type_header = *qi::lit(' ') >> part >> '/' >> sub_part >> *phrase; part = token | extension_token; sub_part = token | extension_token; phrase = qi::lit(';') >> +ws >> attribute >> '=' >> value >> *ws; ws = qi::char_(" \t") | line_sep | comment; line_sep = qi::lexeme[qi::lit(k_crlf)]; attribute = token.alias(); value = token | quoted_string; token = +(qi::char_(" -~") - qi::char_(" ()<>@,;:\\\"/[]?=")); comment = qi::lit('(') >> +(qi::char_(" -~") - ')') >> qi::lit(')'); quoted_string = qi::lit('"') >> +(qi::char_(" -~") - '"') >> qi::lit('"'); extension_token = qi::char_("Xx") >> qi::lit('-') >> token; } qi::rule content_type_header; qi::rule phrase; qi::rule part, sub_part, token, attribute, value, quoted_string, extension_token; qi::rule ws, line_sep, comment; }; template mime_content_type parse_content_type(const string_type &theHeader) { tracer t(__func__); mime_content_type retVal; typename string_type::const_iterator first = theHeader.begin(); mime_content_type_parser ct_parser; bool b = qi::parse(first, theHeader.end(), ct_parser, retVal); if (!b) throw mime_parsing_error("Failed to parse the 'Content-Type' header"); return retVal; } template static string_type get_ct_value(const string_type &ctString, const char *key) { tracer t(__func__); mime_content_type mc = parse_content_type(ctString); for (phrase_container_t::const_iterator iter = mc.phrases.begin(); iter != mc.phrases.end(); ++iter) if (boost::iequals(iter->first, key)) return iter->second; throw std::runtime_error( str(boost::format("Couldn't find Content-Type phrase (%s)") % key)); } // Replace this with a spirit thing later. // we're looking for '; boundary="".*' std::string get_boundary(const std::string &ctString) { tracer t(__func__); return get_ct_value(ctString, "boundary"); } // Read the body of a multipart // Return a Container of containers, where the first is the actual // body, // and the rest are the sub-parts. // Note that the body of the multipart can be empty. // If this is the case, then the first separator need not have a crlf // if the marker is "abcde", we could have: // Note that the separators are really CRLF--abcdeCRLF and // CRLF--abcde--CRLF // // multipart body // --abcde // sub part #1 // --abcde // sub part #2 // --abcde-- // // ** or ** // In this case, the first separator is --abcdeCRLF // // --abcde (no multipart body!) // sub part #1 // --abcde // sub part #2 // --abcde-- typedef std::vector sub_part_t; typedef std::vector sub_parts_t; template struct multipart_body_type { bool prolog_is_missing; bodyContainer body_prolog; sub_parts_t sub_parts; bodyContainer body_epilog; }; // Parse a mulitpart body. // Either "--boundaryCRLF" -- in which case the body is empty // or "CRLF--boundaryCRLF" -- in which // case we return the sequence // // I am deliberately not checking for a termination separator here template struct multipart_body_parser : qi::grammar { multipart_body_parser(const std::string &boundary, bool &isMissing) : multipart_body_parser::base_type(mimeBody), m_is_missing(isMissing) { m_is_missing = false; // Thanks to Michael Caisse for the hint to get this working mimeBody %= bareSep[phx::ref(m_is_missing) = true] | (+(qi::char_ - sep) >> sep); bareSep = qi::lit("--") >> boundary >> crlf; sep = crlf >> bareSep; crlf = qi::lit(k_crlf); } bool &m_is_missing; qi::rule mimeBody; qi::rule bareSep, sep, crlf; }; // Break up a multi-part into its' constituent sub parts. template struct multipart_part_parser : qi::grammar { multipart_part_parser(const std::string &boundary) : multipart_part_parser::base_type(mimeParts) { mimeParts = (+(qi::char_ - sep) % (sep >> crlf)) > terminator; sep = crlf >> qi::lit("--") >> boundary; terminator = sep >> qi::lit("--") >> crlf; crlf = qi::lit(k_crlf); } qi::rule mimeParts; qi::rule sep, terminator, crlf; }; template static void read_multipart_body(Iterator &begin, Iterator end, multipart_body_type &mp_body, const std::string &separator) { tracer t(__func__); typedef bodyContainer innerC; innerC mpBody; multipart_body_parser mb_parser(separator, mp_body.prolog_is_missing); if (!qi::parse(begin, end, mb_parser, mp_body.body_prolog)) throw mime_parsing_error("Failed to parse mime body(1)"); multipart_part_parser mp_parser(separator); if (!qi::parse(begin, end, mp_parser, mp_body.sub_parts)) throw mime_parsing_error("Failed to parse mime body(2)"); std::copy(begin, end, std::back_inserter(mp_body.body_epilog)); #ifdef DUMP_MIME_DATA std::cout << std::endl << ">>****Multipart Body*******" << std::endl; std::cout << str(boost::format( "Body size %d, sub part count = %d, trailer size " "= %d %s") % mp_body.body_prolog.size() % mp_body.sub_parts.size() % mp_body.body_epilog.size() % (mp_body.prolog_is_missing ? "(missing)" : "")) << std::endl; std::cout << std::endl << "****** Multipart Body Prolog *******" << std::endl; std::copy(mp_body.body_prolog.begin(), mp_body.body_prolog.end(), std::ostream_iterator(std::cout)); std::cout << std::endl << "****** Multipart Body Epilog *******" << std::endl; std::copy(mp_body.body_epilog.begin(), mp_body.body_epilog.end(), std::ostream_iterator(std::cout)); std::cout << std::endl << "<<****Multipart Body*******" << std::endl; #endif } template static Container read_simplepart_body(Iterator &begin, Iterator end) { tracer t(__func__); Container retVal; std::copy(begin, end, std::back_inserter(retVal)); #ifdef DUMP_MIME_DATA std::cout << std::endl << ">>****SinglePart Body*******" << std::endl; std::cout << str(boost::format("Body size %d") % retVal.size()) << std::endl; std::copy(retVal.begin(), retVal.end(), std::ostream_iterator(std::cout)); std::cout << std::endl << "<<****SinglePart Body*******" << std::endl; #endif return retVal; } // FIXME: Need to break the headers at 80 chars... template void write_headers(std::ostream &out, const headerList &headers) { if (headers.size() > 0) { for (typename headerList::const_iterator iter = headers.begin(); iter != headers.end(); ++iter) out << iter->first << ':' << iter->second << detail::k_crlf; } out << detail::k_crlf; } template void write_body(std::ostream &out, const bodyContainer &body) { std::copy(body.begin(), body.end(), std::ostream_iterator(out)); } inline void write_boundary(std::ostream &out, std::string boundary, bool isLast, bool leadingCR = true) { if (leadingCR) out << detail::k_crlf; out << "--" << boundary; if (isLast) out << "--"; out << detail::k_crlf; } template static boost::shared_ptr > parse_mime( Iterator &begin, Iterator end, const char *default_content_type = "text/plain"); } template class basic_mime { public: typedef enum { simple_part, multi_part, message_part } part_kind; // Types for headers typedef typename traits::string_type string_type; typedef std::pair headerEntry; typedef std::list headerList; typedef typename headerList::iterator headerIter; typedef typename headerList::const_iterator constHeaderIter; // Types for the parts typedef boost::shared_ptr mimePtr; typedef std::vector partList; typedef typename partList::iterator partIter; typedef typename partList::const_iterator constPartIter; // Type for the body typedef typename traits::body_type bodyContainer; typedef boost::shared_ptr mimeBody; // ----------------------------------------------------------- // Constructors, destructor, assignment, and swap // ----------------------------------------------------------- basic_mime(const char *type, const char *subtype) : m_body_prolog_is_missing(false), m_body(new bodyContainer), m_body_epilog(new bodyContainer) { if (NULL == type || NULL == subtype || 0 == std::strlen(type) || 0 == std::strlen(subtype)) throw std::runtime_error( "Can't create a mime part w/o a type or subtype"); // We start with just two headers, "Content-Type:" and "Mime-Version" // Everything else is optional. m_part_kind = part_kind_from_string_pair(type, subtype); std::string ctString = str(boost::format("%s/%s") % type % subtype); set_header_value(detail::k_content_type_header, ctString); set_header_value(detail::k_mime_version_header, str(boost::format("1.0 (%s %s)") % detail::k_package_name % detail::k_package_version)); } basic_mime(const headerList &theHeaders, const string_type &default_content_type) : m_body_prolog_is_missing(false), m_body(new bodyContainer), m_body_epilog(new bodyContainer), m_default_content_type(default_content_type) { string_type ct = m_default_content_type; constHeaderIter found = std::find_if( theHeaders.begin(), theHeaders.end(), detail::find_mime_header(detail::k_content_type_header)); if (found != theHeaders.end()) ct = found->second; detail::mime_content_type mct = detail::parse_content_type(ct); m_part_kind = part_kind_from_string_pair(mct.type, mct.sub_type); m_headers = theHeaders; } basic_mime(const basic_mime &rhs) : m_part_kind(rhs.m_part_kind), m_headers(rhs.m_headers), m_body_prolog_is_missing(rhs.m_body_prolog_is_missing), m_body(new bodyContainer(*rhs.m_body)), m_body_epilog(new bodyContainer(*rhs.m_body_epilog)), /* m_subparts ( rhs.m_subparts ), */ m_default_content_type( rhs.m_default_content_type) { // Copy the parts -- not just the shared pointers for (typename partList::const_iterator iter = rhs.subpart_begin(); iter != rhs.subpart_end(); ++iter) m_subparts.push_back(mimePtr(new basic_mime(**iter))); } // Simple, copy constructor-based assignment // If this is not efficient enough, then I can optimize it later basic_mime &operator=(const basic_mime &rhs) { basic_mime temp(rhs); this->swap(temp); return *this; } void swap(basic_mime &rhs) throw() { std::swap(m_part_kind, rhs.m_part_kind); std::swap(m_headers, rhs.m_headers); std::swap(m_body_prolog_is_missing, rhs.m_body_prolog_is_missing); std::swap(m_body, rhs.m_body); std::swap(m_body_epilog, rhs.m_body_epilog); std::swap(m_subparts, rhs.m_subparts); std::swap(m_default_content_type, rhs.m_default_content_type); } ~basic_mime() {} // What kind of part is this (simple, multi, message) part_kind get_part_kind() const { return m_part_kind; } // Sub-part information // FIXME: Need some error checking here // No sub-parts for simple parts, for example. size_t part_count() const { return m_subparts.size(); } boost::shared_ptr operator[](std::size_t idx) const { check_subpart_index(idx); return m_subparts[idx]; } void append_part(boost::shared_ptr newPart) { check_subpart_append(); m_subparts.push_back(newPart); } partIter subpart_begin() { return m_subparts.begin(); } partIter subpart_end() { return m_subparts.end(); } constPartIter subpart_begin() const { return m_subparts.begin(); } constPartIter subpart_end() const { return m_subparts.end(); } // Reading the raw headers headerIter header_begin() { return m_headers.begin(); } headerIter header_end() { return m_headers.end(); } constHeaderIter header_begin() const { return m_headers.begin(); } constHeaderIter header_end() const { return m_headers.end(); } // ----------------------------------------------------------- // Header manipulation // ----------------------------------------------------------- // The 'tag' part of the header is still a std::string bool header_exists(const char *key) const { return header_end() != find_header(key); } string_type header_value(const char *key) const { constHeaderIter found = find_header(key); if (found == header_end()) throw std::runtime_error("'header_value' not found"); return found->second; } void set_header_value(const char *key, const string_type &value, bool replace = false) { if (!replace) m_headers.push_back(std::make_pair(std::string(key), value)); else { headerIter found = find_header(key); if (found == m_headers.end()) throw std::runtime_error("'header_value' not found - can't replace"); found->second = value; } } string_type get_content_type_header() const { constHeaderIter found = find_header(detail::k_content_type_header); return found != header_end() ? found->second : m_default_content_type; } string_type get_content_type() const { detail::mime_content_type mct = detail::parse_content_type(get_content_type_header()); return string_type(mct.type) + '/' + mct.sub_type; } // Special purpose helper routine void append_phrase_to_content_type(const char *key, const string_type &value) { headerIter found = find_header(detail::k_content_type_header); // Create a Content-Type header if there isn't one if (m_headers.end() == found) { m_headers.push_back(std::make_pair( std::string(detail::k_content_type_header), m_default_content_type)); found = find_header(detail::k_content_type_header); } detail::mime_content_type mct = detail::parse_content_type(found->second); detail::phrase_container_t::const_iterator p_found = std::find_if(mct.phrases.begin(), mct.phrases.end(), detail::find_mime_header(key)); if (p_found != mct.phrases.end()) throw std::runtime_error("phrase already exists"); found->second += str(boost::format("; %s=\"%s\"") % key % value); } // Body get/set methods mimeBody body() const { return m_body; } mimeBody body_prolog() const { return m_body; } mimeBody body_epilog() const { return m_body_epilog; } std::size_t body_size() const { return m_body->size(); } template void set_body(Iterator begin, Iterator end) { bodyContainer temp; std::copy(begin, end, std::back_inserter(temp)); m_body->swap(temp); } void set_body(const char *contents, size_t sz) { set_body(contents, contents + sz); } void set_body(std::istream &in) { set_body(std::istream_iterator(in), std::istream_iterator()); } void set_body(const bodyContainer &new_body) { *m_body = new_body; } void set_multipart_prolog_is_missing(bool isMissing) { m_body_prolog_is_missing = isMissing; } void set_body_prolog(const bodyContainer &new_body_prolog) { *m_body = new_body_prolog; } void set_body_epilog(const bodyContainer &new_body_epilog) { *m_body_epilog = new_body_epilog; } // ----------------------------------------------------------- // Output // ----------------------------------------------------------- void stream_out(std::ostream &out) { // called by operator << if (m_part_kind == simple_part) { detail::write_headers(out, m_headers); detail::write_body(out, *m_body); } else if (m_part_kind == message_part) { if (m_subparts.size() != 1) throw std::runtime_error( "message part w/wrong number of sub-parts - should be 1"); detail::write_headers(out, m_headers); m_subparts[0]->stream_out(out); } else { // multi-part // Find or invent a boundary string std::string boundary; try { boundary = detail::get_boundary(get_content_type_header()); } catch (std::runtime_error &) { // FIXME: Make boundary strings (more?) unique boundary = str(boost::format("------=_NextPart-%s.%08ld") % detail::k_package_name % std::clock()); append_phrase_to_content_type("boundary", boundary); } // If the body prolog is missing, we don't want a CRLF on the front // of the first sub-part. // Note that there's a (subtle) difference between an zero length // body and a missing one. // See the comments in the parser code for more information. detail::write_headers(out, m_headers); bool writeCR = body_prolog()->size() > 0 || !m_body_prolog_is_missing; detail::write_body(out, *body_prolog()); for (typename partList::const_iterator iter = m_subparts.begin(); iter != m_subparts.end(); ++iter) { detail::write_boundary(out, boundary, false, writeCR); (*iter)->stream_out(out); writeCR = true; } detail::write_boundary(out, boundary, true); detail::write_body(out, *body_epilog()); } // out << detail::k_crlf; } // Build a simple mime part template static basic_mime make_simple_part(const char *type, const char *subtype, Iterator begin, Iterator end) { basic_mime retval(type, subtype); retval.set_body(begin, end); return retval; } // Build a mime part from a pair of iterators template static boost::shared_ptr > parse_mime(Iterator &begin, Iterator end) { return detail::parse_mime(begin, end); } // Build a mime part from a stream static boost::shared_ptr parse_mime(std::istream &in) { boost::spirit::istream_iterator first(in); boost::spirit::istream_iterator last; return parse_mime(first, last); } private: basic_mime(); // Can't create a part w/o a type headerIter find_header(const char *key) { return std::find_if(header_begin(), header_end(), detail::find_mime_header(key)); } constHeaderIter find_header(const char *key) const { return std::find_if(header_begin(), header_end(), detail::find_mime_header(key)); } static part_kind part_kind_from_string_pair(const std::string &type, const std::string &sub_type) { if (boost::iequals(type, "multipart")) return multi_part; part_kind retVal = simple_part; // I expect that this will get more complicated as time goes on.... // // message/delivery-status is a simple type. // RFC 3464 defines message/delivery-status // // The body of a message/delivery-status consists of one or more // "fields" formatted according to the ABNF of RFC 822 header //"fields" // (see [RFC822]). if (boost::iequals(type, "message")) if (!boost::iequals(sub_type, "delivery-status")) retVal = message_part; return retVal; } void check_subpart_index(size_t idx) const { if (get_part_kind() == simple_part) throw std::runtime_error("Simple Mime parts don't have sub-parts"); else if (get_part_kind() == multi_part) { if (idx >= m_subparts.size()) throw std::runtime_error( str(boost::format( "Trying to access part %d (of %d) sub-part to a " "multipart/xxx mime part") % idx % m_subparts.size())); } else { // message-part if (get_part_kind() == message_part) if (m_subparts.size() > 1) throw std::runtime_error( "How did a message/xxx mime parts get more than one " "sub-part?"); if (idx >= m_subparts.size()) throw std::runtime_error( str(boost::format( "Trying to access part %d (of %d) sub-part to a " "message/xxx mime part") % idx % m_subparts.size())); } } void check_subpart_append() const { if (get_part_kind() == simple_part) throw std::runtime_error("Simple Mime parts don't have sub-parts"); else if (get_part_kind() == message_part) { if (m_subparts.size() > 0) throw std::runtime_error( "Can't add a second sub-part to a message/xxx mime part"); } // else { /* Multi-part */ } // We can always add to a multi-part } part_kind m_part_kind; headerList m_headers; bool m_body_prolog_is_missing; // only for multiparts mimeBody m_body; mimeBody m_body_epilog; // only for multiparts partList m_subparts; // only for multiparts or message string_type m_default_content_type; }; namespace detail { template static boost::shared_ptr > parse_mime( Iterator &begin, Iterator end, const char *default_content_type) { tracer t(__func__); typedef typename boost::mime::basic_mime mime_part; shared_ptr retVal(new mime_part( detail::read_headers(begin, end), default_content_type)); std::string content_type = retVal->get_content_type(); #ifdef DUMP_MIME_DATA std::cout << "Content-Type: " << content_type << std::endl; std::cout << str(boost::format("retVal->get_part_kind () = %d") % ((int)retVal->get_part_kind())) << std::endl; #endif if (retVal->get_part_kind() == mime_part::simple_part) retVal->set_body(detail::read_simplepart_body< typename mime_part::bodyContainer, Iterator>(begin, end)); else if (retVal->get_part_kind() == mime_part::message_part) { // If we've got a message/xxxx, then there is no body, and we have // a single // embedded mime_part (which, of course, could be a multipart) retVal->append_part(parse_mime(begin, end)); } else /* multi_part */ { // Find or invent a boundary string std::string part_separator = detail::get_boundary(retVal->get_content_type_header()); const char *cont_type = boost::iequals(content_type, "multipart/digest") ? "message/rfc822" : "text/plain"; detail::multipart_body_type body_and_subParts; detail::read_multipart_body(begin, end, body_and_subParts, part_separator); retVal->set_body_prolog(body_and_subParts.body_prolog); retVal->set_multipart_prolog_is_missing( body_and_subParts.prolog_is_missing); for (typename sub_parts_t::const_iterator iter = body_and_subParts.sub_parts.begin(); iter != body_and_subParts.sub_parts.end(); ++iter) { typedef typename sub_part_t::const_iterator iter_type; iter_type b = iter->begin(); iter_type e = iter->end(); retVal->append_part(parse_mime(b, e, cont_type)); } retVal->set_body_epilog(body_and_subParts.body_epilog); } return retVal; } } // ----------------------------------------------------------- // // Streaming // // ----------------------------------------------------------- template inline std::ostream &operator<<(std::ostream &stream, basic_mime &part) { part.stream_out(stream); return stream; } template inline std::ostream &operator<<(std::ostream &stream, boost::shared_ptr > part) { return stream << *part; } } } BOOST_FUSION_ADAPT_STRUCT(boost::mime::detail::mime_content_type, (std::string, type)(std::string, sub_type)( boost::mime::detail::phrase_container_t, phrases)) #endif // _BOOST_MIME_HPP cpp-netlib-0.11.2-final/boost/network.hpp000066400000000000000000000010111256751517300202540ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_HPP__ #define __NETWORK_HPP__ // Include all headers in network/ // Author: Dean Michael Berris // Date: May 20, 2007 #include // message type implementation #include // protocols implementation #endif // __NETWORK_HPP__ cpp-netlib-0.11.2-final/boost/network/000077500000000000000000000000001256751517300175525ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/constants.hpp000066400000000000000000000067001256751517300223020ustar00rootroot00000000000000#ifndef BOOST_NETWORK_CONSTANTS_HPP_20100808 #define BOOST_NETWORK_CONSTANTS_HPP_20100808 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace impl { template struct constants_narrow { static char const* crlf() { static char crlf_[] = {'\r', '\n', 0}; return crlf_; } static char const* dot() { static char dot_[] = {'.', 0}; return dot_; } static char dot_char() { return '.'; } static char const* http_slash() { static char http_slash_[] = {'H', 'T', 'T', 'P', '/', 0}; return http_slash_; } static char const* space() { static char space_[] = {' ', 0}; return space_; } static char space_char() { return ' '; } static char const* slash() { static char slash_[] = {'/', 0}; return slash_; } static char slash_char() { return '/'; } static char const* host() { static char host_[] = {'H', 'o', 's', 't', 0}; return host_; } static char const* colon() { static char colon_[] = {':', 0}; return colon_; } static char colon_char() { return ':'; } static char const* accept() { static char accept_[] = {'A', 'c', 'c', 'e', 'p', 't', 0}; return accept_; } static char const* default_accept_mime() { static char mime_[] = {'*', '/', '*', 0}; return mime_; } static char const* accept_encoding() { static char accept_encoding_[] = {'A', 'c', 'c', 'e', 'p', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', 0}; return accept_encoding_; } static char const* default_accept_encoding() { static char default_accept_encoding_[] = { 'i', 'd', 'e', 'n', 't', 'i', 't', 'y', ';', 'q', '=', '1', '.', '0', ',', ' ', '*', ';', 'q', '=', '0', 0}; return default_accept_encoding_; } static char const* user_agent() { static char user_agent_[] = {'U', 's', 'e', 'r', '-', 'A', 'g', 'e', 'n', 't', 0}; return user_agent_; } static char const* cpp_netlib_slash() { static char cpp_netlib_slash_[] = {'c', 'p', 'p', '-', 'n', 'e', 't', 'l', 'i', 'b', '/', 0}; return cpp_netlib_slash_; } static char question_mark_char() { return '?'; } static char hash_char() { return '#'; } static char const* connection() { static char connection_[] = {'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 0}; return connection_; } static char const* close() { static char close_[] = {'C', 'l', 'o', 's', 'e', 0}; return close_; } static char const* https() { static char https_[] = "https"; return https_; } }; template struct constants_wide { static wchar_t const* https() { static wchar_t https_[] = L"https"; return https_; } }; } template struct constants : mpl::if_< is_default_string, impl::constants_narrow, typename mpl::if_, impl::constants_wide, unsupported_tag >::type>::type {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_CONSTANTS_HPP_20100808 cpp-netlib-0.11.2-final/boost/network/detail/000077500000000000000000000000001256751517300210145ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/detail/debug.hpp000066400000000000000000000016471256751517300226230ustar00rootroot00000000000000#ifndef BOOST_NETWORK_DEBUG_HPP_20110410 #define BOOST_NETWORK_DEBUG_HPP_20110410 // (c) Copyright 2011 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) /** BOOST_NETWORK_MESSAGE is a debugging macro used by cpp-netlib to print out network-related errors through standard error. This is only useful when BOOST_NETWORK_DEBUG is turned on. Otherwise the macro amounts to a no-op. */ #ifdef BOOST_NETWORK_DEBUG #include #ifndef BOOST_NETWORK_MESSAGE #define BOOST_NETWORK_MESSAGE(msg) \ std::cerr << "[DEBUG " << __FILE__ << ':' << __LINE__ << "]: " << msg \ << std::endl; #endif #else #ifndef BOOST_NETWORK_MESSAGE #define BOOST_NETWORK_MESSAGE(msg) #endif #endif #endif /* end of include guard: BOOST_NETWORK_DEBUG_HPP_20110410 */ cpp-netlib-0.11.2-final/boost/network/detail/directive_base.hpp000066400000000000000000000015651256751517300245040ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ #define __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ /** Defines the base type from which all directives inherit * to allow friend access to message and other types' internals. */ namespace boost { namespace network { namespace detail { template struct directive_base { typedef Tag tag; // explicit directive_base(basic_message & message_) // : _message(message_) protected: ~directive_base() {}; // can only be extended // mutable basic_message & _message; }; } // namespace detail } // namespace network } // namespace boost #endif // __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ cpp-netlib-0.11.2-final/boost/network/detail/wrapper_base.hpp000066400000000000000000000016461256751517300242060ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_DETAIL_WRAPPER_BASE_HPP__ #define __NETWORK_DETAIL_WRAPPER_BASE_HPP__ namespace boost { namespace network { namespace detail { template struct wrapper_base { explicit wrapper_base(Message& message_) : _message(message_) {}; protected: ~wrapper_base() {}; // for extending only Message& _message; }; template struct wrapper_base_const { explicit wrapper_base_const(Message const& message_) : _message(message_) {} protected: ~wrapper_base_const() {}; // for extending only Message const& _message; }; } // namespace detail } // namespace network } // namespace boost #endif // __NETWORK_DETAIL_WRAPPER_BASE_HPP__ cpp-netlib-0.11.2-final/boost/network/include/000077500000000000000000000000001256751517300211755ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/include/http/000077500000000000000000000000001256751517300221545ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/include/http/client.hpp000066400000000000000000000007101256751517300241410ustar00rootroot00000000000000#ifndef BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ #define BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ // Copyright 2009 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // This is the modular include file for using the HTTP Client #include #endif // BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ cpp-netlib-0.11.2-final/boost/network/include/http/server.hpp000066400000000000000000000006351256751517300241770ustar00rootroot00000000000000#ifndef BOOST_NETWORK_INCLUDE_HTTP_SERVER_HPP_ #define BOOST_NETWORK_INCLUDE_HTTP_SERVER_HPP_ // Copyright 2010 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // This is the modular include file for using the HTTP Client #include #endif cpp-netlib-0.11.2-final/boost/network/include/message.hpp000066400000000000000000000007301256751517300233320ustar00rootroot00000000000000#ifndef BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ #define BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ // Copyright 2009 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // This is the modular include file for using the basic message type #include #include #endif // BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ cpp-netlib-0.11.2-final/boost/network/message.hpp000066400000000000000000000100641256751517300217100ustar00rootroot00000000000000// Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_HPP__ #define __NETWORK_MESSAGE_HPP__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** message.hpp * * This header file implements the common message type which * all networking implementations under the boost::network * namespace. The common message type allows for easy message * construction and manipulation suited for networked * application development. */ namespace boost { namespace network { /** The common message type. */ template struct basic_message { public: typedef Tag tag; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::value_type header_type; typedef typename string::type string_type; basic_message() : _headers(), _body(), _source(), _destination() {} basic_message(const basic_message& other) : _headers(other._headers), _body(other._body), _source(other._source), _destination(other._destination) {} basic_message& operator=(basic_message rhs) { rhs.swap(*this); return *this; } void swap(basic_message& other) { std::swap(other._headers, _headers); std::swap(other._body, _body); std::swap(other._source, _source); std::swap(other._destination, _destination); } headers_container_type& headers() { return _headers; } void headers(headers_container_type const& headers_) const { _headers = headers_; } void add_header(typename headers_container_type::value_type const& pair_) const { _headers.insert(pair_); } void remove_header(typename headers_container_type::key_type const& key) const { _headers.erase(key); } headers_container_type const& headers() const { return _headers; } string_type& body() { return _body; } void body(string_type const& body_) const { _body = body_; } string_type const& body() const { return _body; } string_type& source() { return _source; } void source(string_type const& source_) const { _source = source_; } string_type const& source() const { return _source; } string_type& destination() { return _destination; } void destination(string_type const& destination_) const { _destination = destination_; } string_type const& destination() const { return _destination; } private: friend struct detail::directive_base; friend struct detail::wrapper_base >; mutable headers_container_type _headers; mutable string_type _body; mutable string_type _source; mutable string_type _destination; }; template inline void swap(basic_message& left, basic_message& right) { // swap for ADL left.swap(right); } // Commenting this out as we don't need to do this anymore. // BOOST_CONCEPT_ASSERT((Message // >)); // BOOST_CONCEPT_ASSERT((Message // >)); typedef basic_message message; typedef basic_message wmessage; } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_HPP__ cpp-netlib-0.11.2-final/boost/network/message/000077500000000000000000000000001256751517300211765ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/directives.hpp000066400000000000000000000024121256751517300240470ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_DIRECTIVES_HPP__ #define __NETWORK_MESSAGE_DIRECTIVES_HPP__ #include #include #include namespace boost { namespace network { template inline basic_message& operator<<(basic_message& message_, Directive const& directive) { directive(message_); return message_; } BOOST_NETWORK_STRING_DIRECTIVE(source, source_, message.source(source_), message.source = source_); BOOST_NETWORK_STRING_DIRECTIVE(destination, destination_, message.destination(destination_), message.destination = destination_); BOOST_NETWORK_STRING_DIRECTIVE(body, body_, message.body(body_), message.body = body_); } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_DIRECTIVES_HPP__ cpp-netlib-0.11.2-final/boost/network/message/directives/000077500000000000000000000000001256751517300233375ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/directives/detail/000077500000000000000000000000001256751517300246015ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/directives/detail/string_directive.hpp000066400000000000000000000060031256751517300306550ustar00rootroot00000000000000#ifndef BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 #define BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include /** * * To create your own string directive, you can use the preprocessor macro * BOOST_NETWORK_STRING_DIRECTIVE which takes three parameters: the name of * the directive, a name for the variable to use in the directive visitor, * and the body to be implemented in the visitor. An example directive for * setting the source of a message would look something like this given the * BOOST_NETWORK_STRING_DIRECTIVE macro: * * BOOST_NETWORK_STRING_DIRECTIVE(source, source_, * message.source(source_) * , message.source=source_); * */ #ifndef BOOST_NETWORK_STRING_DIRECTIVE #define BOOST_NETWORK_STRING_DIRECTIVE(name, value, body, pod_body) \ template \ struct name##_directive { \ ValueType const& value; \ explicit name##_directive(ValueType const& value_) : value(value_) {} \ name##_directive(name##_directive const& other) : value(other.value) {} \ template class Message> \ typename enable_if, void>::type operator()( \ Message& message) const { \ pod_body; \ } \ template class Message> \ typename enable_if >, void>::type operator()( \ Message& message) const { \ body; \ } \ }; \ \ template \ inline name##_directive name(T const& input) { \ return name##_directive(input); \ } #endif /* BOOST_NETWORK_STRING_DIRECTIVE */ #endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 \ */ cpp-netlib-0.11.2-final/boost/network/message/directives/detail/string_value.hpp000066400000000000000000000022561256751517300300210ustar00rootroot00000000000000#ifndef BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 #define BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace detail { template struct string_value : mpl::if_, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } /* detail */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 */ cpp-netlib-0.11.2-final/boost/network/message/directives/header.hpp000066400000000000000000000045761256751517300253140ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007-2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ #define __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace impl { template struct header_directive { explicit header_directive(KeyType const& header_name, ValueType const& header_value) : _header_name(header_name), _header_value(header_value) {}; template struct pod_directive { template static void eval(Message const& message, T1 const& key, T2 const& value) { typedef typename Message::headers_container_type::value_type value_type; value_type value_ = {key, value}; message.headers.insert(message.headers.end(), value_); } }; template struct normal_directive { template static void eval(Message const& message, T1 const& key, T2 const& value) { typedef typename Message::headers_container_type::value_type value_type; message.add_header(value_type(key, value)); } }; template struct directive_impl : mpl::if_, pod_directive, normal_directive >::type {}; template void operator()(Message const& msg) const { directive_impl::eval(msg, _header_name, _header_value); } private: KeyType const& _header_name; ValueType const& _header_value; }; } // namespace impl template inline impl::header_directive header(T1 const& header_name, T2 const& header_value) { return impl::header_directive(header_name, header_value); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ cpp-netlib-0.11.2-final/boost/network/message/directives/remove_header.hpp000066400000000000000000000023301256751517300266530ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP #define NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP #include namespace boost { namespace network { template struct basic_message; namespace impl { template struct remove_header_directive { explicit remove_header_directive(T header_name) : header_name_(header_name) {}; template void operator()(basic_message& msg) const { msg.headers().erase(header_name_); } private: mutable T header_name_; }; } // namespace impl inline impl::remove_header_directive remove_header( std::string header_name) { return impl::remove_header_directive(header_name); } inline impl::remove_header_directive remove_header( std::wstring header_name) { return impl::remove_header_directive(header_name); } } // namespace network } // namespace boost #endif // NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP cpp-netlib-0.11.2-final/boost/network/message/message_concept.hpp000066400000000000000000000040631256751517300250510ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 #define BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 // Copyright (c) Glyn Matthews 2010. // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include namespace boost { namespace network { template struct Message : DefaultConstructible, CopyConstructible, Assignable { typedef typename M::string_type string_type; typedef typename M::headers_container_type headers_container_type; BOOST_CONCEPT_USAGE(Message) { M message_; swap(message, message_); typedef typename traits::body::type body_type; typedef typename traits::source::type source_type; typedef typename traits::destination::type destination_type; headers_container_type headers_ = headers(message); string_type body_ = body(message); string_type source_ = source(message); string_type destination_ = destination(message); message << source(source_type()) << destination(destination_type()) << header(string_type(), string_type()) << body(body_type()); add_header(message, string_type(), string_type()); remove_header(message, string_type()); clear_headers(message); source(message, source_type()); destination(message, destination_type()); body(message, body_type()); (void)headers_; (void)body_; (void)source_; (void)destination_; } private: M message; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 cpp-netlib-0.11.2-final/boost/network/message/modifiers/000077500000000000000000000000001256751517300231575ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/modifiers/add_header.hpp000066400000000000000000000036341256751517300257360ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 #define BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace impl { template inline typename enable_if< mpl::and_ >, mpl::not_ > >, void>::type add_header(Message& message, KeyType const& key, ValueType const& value, Tag) { message.headers().insert(std::make_pair(key, value)); } template inline typename enable_if >, is_async >, void>::type add_header(Message& message, KeyType const& key, ValueType const& value, Tag) { typedef typename Message::header_type header_type; message.add_header(header_type(key, value)); } template inline typename enable_if, void>::type add_header( Message& message, KeyType const& key, ValueType const& value, Tag) { typename Message::header_type header = {key, value}; message.headers.insert(message.headers.end(), header); } } template class Message, class KeyType, class ValueType> inline void add_header(Message& message, KeyType const& key, ValueType const& value) { impl::add_header(message, key, value, Tag()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/modifiers/body.hpp000066400000000000000000000021261256751517300246260ustar00rootroot00000000000000#ifndef BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 #define BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template class Message, class ValueType> inline void body_impl(Message& message, ValueType const& body, tags::pod) { message.body = body; } template class Message, class ValueType> inline void body_impl(Message& message, ValueType const& body, tags::normal) { message.body(body); } template class Message, class ValueType> inline void body(Message& message, ValueType const& body_) { body_impl(message, body_, typename pod_or_normal::type()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/modifiers/clear_headers.hpp000066400000000000000000000035521256751517300264560ustar00rootroot00000000000000#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 #define BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace impl { template inline typename enable_if< mpl::and_ >, mpl::not_ > >, void>::type clear_headers(Message const &message, Tag const &) { (typename Message::headers_container_type()).swap(message.headers()); } template inline typename enable_if, void>::type clear_headers( Message const &message, Tag const &) { (typename Message::headers_container_type()).swap(message.headers); } template inline typename enable_if >, is_async >, void>::type clear_headers(Message const &message, Tag const &) { boost::promise header_promise; boost::shared_future headers_future( header_promise.get_future()); message.headers(headers_future); header_promise.set_value(typename Message::headers_container_type()); } } // namespace impl template class Message> inline void clear_headers(Message const &message) { impl::clear_headers(message, Tag()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/modifiers/destination.hpp000066400000000000000000000024231256751517300262120ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 #define BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace impl { template inline void destination(Message const &message, ValueType const &destination_, Tag const &, mpl::false_ const &) { message.destination(destination_); } template inline void destination(Message const &message, ValueType const &destination_, Tag const &, mpl::true_ const &) { message.destination(destination_); } } template class Message, class ValueType> inline void destination(Message const &message, ValueType const &destination_) { impl::destination(message, destination_, Tag(), is_async()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/modifiers/remove_header.hpp000066400000000000000000000037331256751517300265030ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 #define BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace impl { template inline typename enable_if< mpl::and_ >, mpl::not_ > >, void>::type remove_header(Message& message, KeyType const& key, Tag) { message.headers().erase(key); } template inline typename enable_if >, is_async >, void>::type remove_header(Message& message, KeyType const& key, Tag) { message.remove_header(key); } template struct iequals_pred { KeyType const& key; iequals_pred(KeyType const& key) : key(key) {} template bool operator()(Header& other) const { return boost::iequals(key, name(other)); } }; template inline typename enable_if, void>::type remove_header( Message& message, KeyType const& key, Tag) { message.headers.erase( boost::remove_if(message.headers, iequals_pred(key)), message.headers.end()); } } // namespace impl template class Message, class KeyType> inline void remove_header(Message& message, KeyType const& key) { impl::remove_header(message, key, Tag()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/modifiers/source.hpp000066400000000000000000000022271256751517300251730ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 #define BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace impl { template inline void source(Message const &message, ValueType const &source_, Tag const &, mpl::false_ const &) { message.source(source_); } template inline void source(Message const &message, ValueType const &source_, Tag const &, mpl::true_ const &) { message.source(source_); } } // namespace impl template class Message, class ValueType> inline void source(Message const &message, ValueType const &source_) { impl::source(message, source_, Tag(), is_async()); } } // namespace network } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 cpp-netlib-0.11.2-final/boost/network/message/traits/000077500000000000000000000000001256751517300225045ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/traits/body.hpp000066400000000000000000000024151256751517300241540ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 #define BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace traits { template struct unsupported_tag; template struct body : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } // namespace traits } /* network */ } /* boost */ #endif // BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 cpp-netlib-0.11.2-final/boost/network/message/traits/destination.hpp000066400000000000000000000024151256751517300255400ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 #define BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace traits { template struct unsupported_tag; template struct destination : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } // namespace traits } /* network */ } /* boost */ #endif // BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 cpp-netlib-0.11.2-final/boost/network/message/traits/headers.hpp000066400000000000000000000035461256751517300246400ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 #define BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace traits { template struct unsupported_tag; template struct header_key : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; template struct header_value : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } // namespace traits } /* network */ } /* boost */ #endif // BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 cpp-netlib-0.11.2-final/boost/network/message/traits/source.hpp000066400000000000000000000023701256751517300245170ustar00rootroot00000000000000#ifndef BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 #define BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace traits { template struct unsupported_tag; template struct source : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } // namespace traits } /* network */ } /* boost */ #endif // BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 cpp-netlib-0.11.2-final/boost/network/message/transformers.hpp000066400000000000000000000032141256751517300244340ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_TRANSFORMERS_HPP__ #define __NETWORK_MESSAGE_TRANSFORMERS_HPP__ /** transformers.hpp * * Pulls in all the transformers files. */ #include #include #include #include namespace boost { namespace network { namespace impl { template struct get_real_algorithm { typedef typename boost::function_traits< typename boost::remove_pointer::type>::result_type:: template type::type>::result_type> type; }; template struct transform_impl : public get_real_algorithm::type {}; } // namspace impl template inline impl::transform_impl transform(Algorithm, Selector) { return impl::transform_impl(); } template inline basic_message& operator<<( basic_message& msg_, impl::transform_impl const& transformer) { transformer(msg_); return msg_; } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_TRANSFORMERS_HPP__ cpp-netlib-0.11.2-final/boost/network/message/transformers/000077500000000000000000000000001256751517300237235ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/transformers/selectors.hpp000066400000000000000000000031141256751517300264360ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ #define __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ namespace boost { namespace network { namespace selectors { struct source_selector; struct destination_selector; } // namespace selectors selectors::source_selector source_(selectors::source_selector); selectors::destination_selector destination_(selectors::destination_selector); namespace selectors { struct source_selector { private: source_selector() {}; source_selector(source_selector const &) {}; friend source_selector boost::network::source_(source_selector); }; struct destination_selector { private: destination_selector() {}; destination_selector(destination_selector const &) {}; friend destination_selector boost::network::destination_( destination_selector); }; } // namespace selectors typedef selectors::source_selector (*source_selector_t)( selectors::source_selector); typedef selectors::destination_selector (*destination_selector_t)( selectors::destination_selector); inline selectors::source_selector source_(selectors::source_selector) { return selectors::source_selector(); } inline selectors::destination_selector destination_( selectors::destination_selector) { return selectors::destination_selector(); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ cpp-netlib-0.11.2-final/boost/network/message/transformers/to_lower.hpp000066400000000000000000000041541256751517300262720ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ #define __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ #include /** to_lower.hpp * * Implements the to_lower transformer. This applies * the to_lower string algorithm to a string, which * is selected by the appropriate selector. * * This defines a type, to be applied using template * metaprogramming on the selected string target. */ namespace boost { namespace network { namespace impl { template struct to_lower_transformer {}; template <> struct to_lower_transformer { template void operator()(basic_message &message_) const { boost::to_lower(message_.source()); } protected: ~to_lower_transformer() {} }; template <> struct to_lower_transformer { template void operator()(basic_message &message_) const { boost::to_lower(message_.destination()); } protected: ~to_lower_transformer() {}; }; } // namespace impl namespace detail { struct to_lower_placeholder_helper; } detail::to_lower_placeholder_helper to_lower_( detail::to_lower_placeholder_helper); namespace detail { struct to_lower_placeholder_helper { template struct type : public impl::to_lower_transformer {}; private: to_lower_placeholder_helper() {} to_lower_placeholder_helper(to_lower_placeholder_helper const &) {} friend to_lower_placeholder_helper boost::network::to_lower_( to_lower_placeholder_helper); }; } typedef detail::to_lower_placeholder_helper (*to_lower_placeholder)( detail::to_lower_placeholder_helper); inline detail::to_lower_placeholder_helper to_lower_( detail::to_lower_placeholder_helper) { return detail::to_lower_placeholder_helper(); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ cpp-netlib-0.11.2-final/boost/network/message/transformers/to_upper.hpp000066400000000000000000000041551256751517300262760ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ #define __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ #include /** to_upper.hpp * * Implements the to_upper transformer. This applies * the to_upper string algorithm to a string, which * is selected by the appropriate selector. * * This defines a type, to be applied using template * metaprogramming on the selected string target. */ namespace boost { namespace network { namespace impl { template struct to_upper_transformer {}; template <> struct to_upper_transformer { template void operator()(basic_message &message_) const { boost::to_upper(message_.source()); } protected: ~to_upper_transformer() {}; }; template <> struct to_upper_transformer { template void operator()(basic_message &message_) const { boost::to_upper(message_.destination()); } protected: ~to_upper_transformer() {}; }; } // namespace impl namespace detail { struct to_upper_placeholder_helper; } detail::to_upper_placeholder_helper to_upper_( detail::to_upper_placeholder_helper); namespace detail { struct to_upper_placeholder_helper { template struct type : public impl::to_upper_transformer {}; private: to_upper_placeholder_helper() {} to_upper_placeholder_helper(to_upper_placeholder_helper const &) {} friend to_upper_placeholder_helper boost::network::to_upper_( to_upper_placeholder_helper); }; } typedef detail::to_upper_placeholder_helper (*to_upper_placeholder)( detail::to_upper_placeholder_helper); inline detail::to_upper_placeholder_helper to_upper_( detail::to_upper_placeholder_helper) { return detail::to_upper_placeholder_helper(); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ cpp-netlib-0.11.2-final/boost/network/message/wrappers.hpp000066400000000000000000000011641256751517300235540ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_WRAPPERS_HPP__ #define __NETWORK_MESSAGE_WRAPPERS_HPP__ /** wrappers.hpp * * Pulls in all the wrapper header files. */ #include #include #include #include #endif // __NETWORK_MESSAGE_WRAPPERS_HPP__ cpp-netlib-0.11.2-final/boost/network/message/wrappers/000077500000000000000000000000001256751517300230415ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/message/wrappers/body.hpp000066400000000000000000000061001256751517300245040ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ #define __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ #include #include #include namespace boost { namespace network { template struct body_range { typedef typename boost::iterator_range< typename Message::string_type::const_iterator> type; }; namespace impl { template struct body_wrapper : public detail::wrapper_base > { typedef basic_message message_type; typedef typename string::type string_type; typedef detail::wrapper_base > wrapper_base; explicit body_wrapper(basic_message& message_) : wrapper_base(message_) {}; operator string_type() const { return string_type(wrapper_base::_message.body()); }; std::size_t size() const { return wrapper_base::_message.body().size(); } operator boost::iterator_range< typename boost::range_iterator::type>() const { return boost::make_iterator_range(wrapper_base::_message.body()); } typename string_type::const_iterator begin() const { return wrapper_base::_message.body().begin(); } typename string_type::const_iterator end() const { return wrapper_base::_message.body().end(); } }; template struct body_wrapper_const : public detail::wrapper_base_const > { typedef basic_message message_type; typedef typename string::type string_type; typedef detail::wrapper_base_const > wrapper_base; explicit body_wrapper_const(basic_message const& message_) : wrapper_base(message_) {}; operator string_type() const { return string_type(wrapper_base::_message.body()); } std::size_t size() const { return wrapper_base::_message.body().size(); } operator boost::range_iterator() const { return boost::make_iterator_range(wrapper_base::_message.body()); } }; template inline std::ostream& operator<<(std::ostream& os, body_wrapper const& body) { os << static_cast::string_type>(body); return os; } template inline std::ostream& operator<<(std::ostream& os, body_wrapper_const const& body) { os << static_cast::string_type>(body); return os; } } // namespace impl template inline impl::body_wrapper const body(basic_message& message_) { return impl::body_wrapper(message_); } template inline impl::body_wrapper_const const body( basic_message const& message_) { return impl::body_wrapper_const(message_); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ cpp-netlib-0.11.2-final/boost/network/message/wrappers/destination.hpp000066400000000000000000000022501256751517300260720ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ #define __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ #include namespace boost { namespace network { namespace impl { template struct destination_wrapper : public detail::wrapper_base > { typedef Tag tag; typedef basic_message message_type; typedef typename string::type string_type; typedef detail::wrapper_base > wrapper_base; explicit destination_wrapper(message_type& message_) : wrapper_base(message_) {}; operator string_type() const { return string_type(wrapper_base::_message.destination()); }; }; } // namespace impl template inline typename string::type destination(basic_message& message_) { return impl::destination_wrapper(message_); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ cpp-netlib-0.11.2-final/boost/network/message/wrappers/headers.hpp000066400000000000000000000063051256751517300251710ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ #define __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ #include #include #include #include #include namespace boost { namespace network { /// Template metaprogram to get the range type for a message template struct headers_range { typedef typename headers_container::type headers_container_type; typedef typename boost::iterator_range< typename headers_container_type::const_iterator> type; }; template struct basic_message; /** headers wrapper for messages. * * This exposes an interface similar to a map, indexable * using operator[] taking a string as the index and returns * a range of iterators (std::pair) * whose keys are all equal to the index string. * * This type is also convertible to a * headers_range >::type * Which allows for full range support. * * The type is also convertible to a * headers_container::type * Which copies the headers from the wrapped message. * */ namespace impl { template struct headers_wrapper : public detail::wrapper_base_const > { typedef Tag tag; typedef basic_message message_type; typedef typename string::type string_type; typedef typename headers_range::type range_type; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::const_iterator const_iterator; typedef typename headers_container_type::iterator iterator; typedef detail::wrapper_base_const > wrapper_base; explicit headers_wrapper(basic_message const& message_) : wrapper_base(message_) {}; range_type operator[](string_type const& key) const { return headers_wrapper::_message.headers().equal_range(key); }; typename message_type::headers_container_type::size_type count( string_type const& key) const { return headers_wrapper::_message.headers().count(key); }; const_iterator begin() const { return headers_wrapper::_message.headers().begin(); }; const_iterator end() const { return headers_wrapper::_message.headers().end(); }; operator range_type() { return make_iterator_range(headers_wrapper::_message.headers().begin(), headers_wrapper::_message.headers().end()); }; operator headers_container_type() { return headers_wrapper::_message.headers(); } }; } // namespace impl /// Factory method to create the right wrapper object template inline impl::headers_wrapper headers(basic_message const& message_) { return impl::headers_wrapper(message_); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ cpp-netlib-0.11.2-final/boost/network/message/wrappers/source.hpp000066400000000000000000000022021256751517300250460ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ #define __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ #include namespace boost { namespace network { namespace impl { template struct source_wrapper : public detail::wrapper_base > { typedef Tag tag; typedef basic_message message_type; typedef typename string::type string_type; typedef detail::wrapper_base > wrapper_base; explicit source_wrapper(basic_message& message_) : wrapper_base(message_) {}; operator string_type() const { return string_type(wrapper_base::_message.source()); }; }; } // namespace impl template inline typename string::type source(basic_message& message_) { return impl::source_wrapper(message_); } } // namespace network } // namespace boost #endif // __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ cpp-netlib-0.11.2-final/boost/network/message_fwd.hpp000066400000000000000000000007101256751517300225450ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __2008817MESSAGE_FWD_INC__ #define __2008817MESSAGE_FWD_INC__ namespace boost { namespace network { template struct basic_message; } // namespace boost } // namespace network #endif // __2008817MESSAGE_FWD_INC__ cpp-netlib-0.11.2-final/boost/network/protocol.hpp000066400000000000000000000010551256751517300221250ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_PROTOCOLS_20070908_1_HPP__ #define __NETWORK_PROTOCOLS_20070908_1_HPP__ // Include all protocol implementation headers in protocol/* // Author: Dean Michael Berris // Date Created: Oct. 08, 2007 #include // include HTTP implementation #endif // __NETWORK_PROTOCOLS_20070908-1_HPP__ cpp-netlib-0.11.2-final/boost/network/protocol/000077500000000000000000000000001256751517300214135ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http.hpp000066400000000000000000000012511256751517300231020ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007, 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_PROTOCOL_HTTP_20070908_1_HPP__ #define __NETWORK_PROTOCOL_HTTP_20070908_1_HPP__ // Include HTTP implementation headers // Author: Dean Michael Berris // Date Created: Oct. 08, 2007 #include #include #include #include #endif // __NETWORK_PROTOCOL_HTTP_20070908-1_HPP__ cpp-netlib-0.11.2-final/boost/network/protocol/http/000077500000000000000000000000001256751517300223725ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/algorithms/000077500000000000000000000000001256751517300245435ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/algorithms/linearize.hpp000066400000000000000000000153021256751517300272370ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 #define BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Copyright 2014 Jussi Lyytinen // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct linearize_header { typedef typename string::type string_type; template struct result; template struct result { typedef string_type type; }; template BOOST_CONCEPT_REQUIRES(((Header::type>)), (string_type)) operator()(ValueType& header) { typedef typename ostringstream::type output_stream; typedef constants consts; output_stream header_line; header_line << name(header) << consts::colon() << consts::space() << value(header) << consts::crlf(); return header_line.str(); } }; template BOOST_CONCEPT_REQUIRES(((ClientRequest)), (OutputIterator)) linearize(Request const& request, typename Request::string_type const& method, unsigned version_major, unsigned version_minor, OutputIterator oi) { typedef typename Request::tag Tag; typedef constants consts; typedef typename string::type string_type; static string_type http_slash = consts::http_slash(), accept = consts::accept(), accept_mime = consts::default_accept_mime(), accept_encoding = consts::accept_encoding(), default_accept_encoding = consts::default_accept_encoding(), crlf = consts::crlf(), host = consts::host(), connection = consts::connection(), close = consts::close(); boost::copy(method, oi); *oi = consts::space_char(); if (request.path().empty() || request.path()[0] != consts::slash_char()) *oi = consts::slash_char(); boost::copy(request.path(), oi); if (!request.query().empty()) { *oi = consts::question_mark_char(); boost::copy(request.query(), oi); } if (!request.anchor().empty()) { *oi = consts::hash_char(); boost::copy(request.anchor(), oi); } *oi = consts::space_char(); boost::copy(http_slash, oi); string_type version_major_str = boost::lexical_cast(version_major), version_minor_str = boost::lexical_cast(version_minor); boost::copy(version_major_str, oi); *oi = consts::dot_char(); boost::copy(version_minor_str, oi); boost::copy(crlf, oi); // We need to determine whether we've seen any of the following headers // before setting the defaults. We use a bitset to keep track of the // defaulted headers. enum { ACCEPT, ACCEPT_ENCODING, HOST, CONNECTION, MAX }; std::bitset found_headers; static char const* defaulted_headers[][2] = { {consts::accept(), consts::accept() + std::strlen(consts::accept())}, {consts::accept_encoding(), consts::accept_encoding() + std::strlen(consts::accept_encoding())}, {consts::host(), consts::host() + std::strlen(consts::host())}, {consts::connection(), consts::connection() + std::strlen(consts::connection())}}; typedef typename headers_range::type headers_range; typedef typename range_value::type headers_value; BOOST_FOREACH(const headers_value & header, headers(request)) { string_type header_name = name(header), header_value = value(header); // Here we check that we have not seen an override to the defaulted // headers. for (int header_index = 0; header_index < MAX; ++header_index) if (std::distance(header_name.begin(), header_name.end()) == std::distance(defaulted_headers[header_index][0], defaulted_headers[header_index][1]) && std::equal(header_name.begin(), header_name.end(), defaulted_headers[header_index][0], algorithm::is_iequal())) found_headers.set(header_index, true); // We ignore empty headers. if (header_value.empty()) continue; boost::copy(header_name, oi); *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(header_value, oi); boost::copy(crlf, oi); } if (!found_headers[HOST]) { boost::copy(host, oi); *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(request.host(), oi); boost::optional port_ = #if (_MSC_VER >= 1600 && BOOST_VERSION > 105500) port(request).as_optional(); #else port(request); #endif if (port_) { string_type port_str = boost::lexical_cast(*port_); *oi = consts::colon_char(); boost::copy(port_str, oi); } boost::copy(crlf, oi); } if (!found_headers[ACCEPT]) { boost::copy(accept, oi); *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(accept_mime, oi); boost::copy(crlf, oi); } if (version_major == 1u && version_minor == 1u && !found_headers[ACCEPT_ENCODING]) { boost::copy(accept_encoding, oi); *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(default_accept_encoding, oi); boost::copy(crlf, oi); } if (!connection_keepalive::value && !found_headers[CONNECTION]) { boost::copy(connection, oi); *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(close, oi); boost::copy(crlf, oi); } boost::copy(crlf, oi); typename body_range::type body_data = body(request).range(); return boost::copy(body_data, oi); } } /* http */ } /* net */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client.hpp000066400000000000000000000045221256751517300243640ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 // Copyright Dean Michael Berris 2007-2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_client : basic_client_facade { private: typedef basic_client_facade base_facade_type; public: typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; typedef Tag tag_type; typedef client_options options; // Constructors // ================================================================= // This constructor takes a single options argument of type // client_options. See boost/network/protocol/http/client/options.hpp // for more details. explicit basic_client(options const& options) : base_facade_type(options) {} // This default constructor sets up the default options. basic_client() : base_facade_type(options()) {} // // ================================================================= }; #ifndef BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG #define BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG tags::http_async_8bit_udp_resolve #endif typedef basic_client client; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/000077500000000000000000000000001256751517300236505ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/client/async_impl.hpp000066400000000000000000000101661256751517300265230ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 // Copyright Dean Michael Berris 2010. // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_client_impl; namespace impl { template struct async_client : connection_policy::type { typedef typename connection_policy::type connection_base; typedef typename resolver::type resolver_type; typedef typename string::type string_type; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; async_client(bool cache_resolved, bool follow_redirect, bool always_verify_peer, int timeout, boost::shared_ptr service, optional const& certificate_filename, optional const& verify_path, optional const& certificate_file, optional const& private_key_file, optional const& ciphers, long ssl_options) : connection_base(cache_resolved, follow_redirect, timeout), service_ptr(service.get() ? service : boost::make_shared()), service_(*service_ptr), resolver_(service_), sentinel_(new boost::asio::io_service::work(service_)), certificate_filename_(certificate_filename), verify_path_(verify_path), certificate_file_(certificate_file), private_key_file_(private_key_file), ciphers_(ciphers), ssl_options_(ssl_options), always_verify_peer_(always_verify_peer) { connection_base::resolver_strand_.reset( new boost::asio::io_service::strand(service_)); if (!service) lifetime_thread_.reset(new boost::thread( boost::bind(&boost::asio::io_service::run, &service_))); } ~async_client() throw() { sentinel_.reset(); } void wait_complete() { sentinel_.reset(); if (lifetime_thread_.get()) { lifetime_thread_->join(); lifetime_thread_.reset(); } } basic_response const request_skeleton( basic_request const& request_, string_type const& method, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { typename connection_base::connection_ptr connection_; connection_ = connection_base::get_connection( resolver_, request_, always_verify_peer_, certificate_filename_, verify_path_, certificate_file_, private_key_file_, ciphers_, ssl_options_); return connection_->send_request(method, request_, get_body, callback, generator); } boost::shared_ptr service_ptr; boost::asio::io_service& service_; resolver_type resolver_; boost::shared_ptr sentinel_; boost::shared_ptr lifetime_thread_; optional certificate_filename_; optional verify_path_; optional certificate_file_; optional private_key_file_; optional ciphers_; long ssl_options_; bool always_verify_peer_; }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/000077500000000000000000000000001256751517300260075ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/async_base.hpp000066400000000000000000000065051256751517300306350ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 // Copryight 2013 Google, Inc. // Copyright 2010 Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { namespace http { namespace impl { template struct async_connection_base { typedef async_connection_base this_type; typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename resolver_base::resolve_function resolve_function; typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; typedef iterator_range char_const_range; typedef function body_callback_function_type; typedef function body_generator_function_type; typedef shared_ptr connection_ptr; // This is the factory function which constructs the appropriate async // connection implementation with the correct delegate chosen based on // the // tag. static connection_ptr new_connection( resolve_function resolve, resolver_type &resolver, bool follow_redirect, bool always_verify_peer, bool https, int timeout, optional certificate_filename = optional(), optional const &verify_path = optional(), optional certificate_file = optional(), optional private_key_file = optional(), optional ciphers = optional(), long ssl_options = 0) { typedef http_async_connection async_connection; typedef typename delegate_factory::type delegate_factory_type; connection_ptr temp; temp.reset(new async_connection( resolver, resolve, follow_redirect, timeout, delegate_factory_type::new_connection_delegate( resolver.get_io_service(), https, always_verify_peer, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options))); BOOST_ASSERT(temp.get() != 0); return temp; } // This is the pure virtual entry-point for all asynchronous // connections. virtual response start(request const &request, string_type const &method, bool get_body, body_callback_function_type callback, body_generator_function_type generator) = 0; virtual ~async_connection_base() {} }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/async_normal.hpp000066400000000000000000000523361256751517300312160ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google,Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { namespace impl { template struct async_connection_base; namespace placeholders = boost::asio::placeholders; template struct http_async_connection : async_connection_base, protected http_async_protocol_handler, boost::enable_shared_from_this< http_async_connection > { typedef async_connection_base base; typedef http_async_protocol_handler protocol_base; typedef typename base::resolver_type resolver_type; typedef typename base::resolver_base::resolver_iterator resolver_iterator; typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; typedef typename base::response response; typedef typename base::string_type string_type; typedef typename base::request request; typedef typename base::resolver_base::resolve_function resolve_function; typedef typename base::body_callback_function_type body_callback_function_type; typedef typename base::body_generator_function_type body_generator_function_type; typedef http_async_connection this_type; typedef typename delegate_factory::type delegate_factory_type; typedef typename delegate_factory_type::connection_delegate_ptr connection_delegate_ptr; http_async_connection(resolver_type& resolver, resolve_function resolve, bool follow_redirect, int timeout, connection_delegate_ptr delegate) : timeout_(timeout), timer_(resolver.get_io_service()), is_timedout_(false), follow_redirect_(follow_redirect), resolver_(resolver), resolve_(resolve), request_strand_(resolver.get_io_service()), delegate_(delegate) {} // This is the main entry point for the connection/request pipeline. // We're // overriding async_connection_base<...>::start(...) here which is // called // by the client. virtual response start(request const& request, string_type const& method, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { response response_; this->init_response(response_, get_body); linearize(request, method, version_major, version_minor, std::ostreambuf_iterator::type>( &command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); string_type host_ = host(request); boost::uint16_t source_port = request.source_port(); resolve_(resolver_, host_, port_, request_strand_.wrap(boost::bind( &this_type::handle_resolved, this_type::shared_from_this(), host_, port_, source_port, get_body, callback, generator, boost::arg<1>(), boost::arg<2>()))); if (timeout_ > 0) { timer_.expires_from_now(boost::posix_time::seconds(timeout_)); timer_.async_wait(request_strand_.wrap( boost::bind(&this_type::handle_timeout, this_type::shared_from_this(), boost::arg<1>()))); } return response_; } private: http_async_connection(http_async_connection const&); // = delete void set_errors(boost::system::error_code const& ec) { boost::system::system_error error(ec); this->version_promise.set_exception(boost::copy_exception(error)); this->status_promise.set_exception(boost::copy_exception(error)); this->status_message_promise.set_exception(boost::copy_exception(error)); this->headers_promise.set_exception(boost::copy_exception(error)); this->source_promise.set_exception(boost::copy_exception(error)); this->destination_promise.set_exception(boost::copy_exception(error)); this->body_promise.set_exception(boost::copy_exception(error)); this->timer_.cancel(); } void handle_timeout(boost::system::error_code const& ec) { if (!ec) delegate_->disconnect(); is_timedout_ = true; } void handle_resolved(string_type host, boost::uint16_t port, boost::uint16_t source_port, bool get_body, body_callback_function_type callback, body_generator_function_type generator, boost::system::error_code const& ec, resolver_iterator_pair endpoint_range) { if (!ec && !boost::empty(endpoint_range)) { // Here we deal with the case that there was an error encountered // and // that there's still more endpoints to try connecting to. resolver_iterator iter = boost::begin(endpoint_range); asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); delegate_->connect( endpoint, host, source_port, request_strand_.wrap(boost::bind( &this_type::handle_connected, this_type::shared_from_this(), host, port, source_port, get_body, callback, generator, std::make_pair(++iter, resolver_iterator()), placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); boost::iterator_range range; if (callback) callback(range, ec); } } void handle_connected(string_type host, boost::uint16_t port, boost::uint16_t source_port, bool get_body, body_callback_function_type callback, body_generator_function_type generator, resolver_iterator_pair endpoint_range, boost::system::error_code const& ec) { if (is_timedout_) { set_errors(asio::error::timed_out); } else if (!ec) { BOOST_ASSERT(delegate_.get() != 0); delegate_->write( command_streambuf, request_strand_.wrap(boost::bind( &this_type::handle_sent_request, this_type::shared_from_this(), get_body, callback, generator, placeholders::error, placeholders::bytes_transferred))); } else { if (!boost::empty(endpoint_range)) { resolver_iterator iter = boost::begin(endpoint_range); asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); delegate_->connect( endpoint, host, source_port, request_strand_.wrap(boost::bind( &this_type::handle_connected, this_type::shared_from_this(), host, port, source_port, get_body, callback, generator, std::make_pair(++iter, resolver_iterator()), placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); boost::iterator_range range; if (callback) callback(range, ec); } } } enum state_t { version, status, status_message, headers, body }; void handle_sent_request(bool get_body, body_callback_function_type callback, body_generator_function_type generator, boost::system::error_code const& ec, std::size_t bytes_transferred) { // TODO(dberris): review parameter necessity. (void)bytes_transferred; if (!is_timedout_ && !ec) { if (generator) { // Here we write some more data that the generator provides, // before // we wait for data from the server. string_type chunk; if (generator(chunk)) { // At this point this means we have more data to write, so we // write // it out. std::copy(chunk.begin(), chunk.end(), std::ostreambuf_iterator::type>( &command_streambuf)); delegate_->write( command_streambuf, request_strand_.wrap(boost::bind( &this_type::handle_sent_request, this_type::shared_from_this(), get_body, callback, generator, placeholders::error, placeholders::bytes_transferred))); return; } } delegate_->read_some( boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), version, get_body, callback, placeholders::error, placeholders::bytes_transferred))); } else { set_errors(is_timedout_ ? asio::error::timed_out : ec); } } void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const& ec, std::size_t bytes_transferred) { static const long short_read_error = 335544539; bool is_ssl_short_read_error = #ifdef BOOST_NETWORK_ENABLE_HTTPS ec.category() == asio::error::ssl_category && ec.value() == short_read_error; #else false && short_read_error; #endif if (!is_timedout_ && (!ec || ec == boost::asio::error::eof || is_ssl_short_read_error)) { logic::tribool parsed_ok; size_t remainder; switch (state) { case version: if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_version( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), version, get_body, callback, placeholders::error, placeholders::bytes_transferred)), bytes_transferred); if (!parsed_ok || indeterminate(parsed_ok)) return; case status: if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_status( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), status, get_body, callback, placeholders::error, placeholders::bytes_transferred)), bytes_transferred); if (!parsed_ok || indeterminate(parsed_ok)) return; case status_message: if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_status_message( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), status_message, get_body, callback, placeholders::error, placeholders::bytes_transferred)), bytes_transferred); if (!parsed_ok || indeterminate(parsed_ok)) return; case headers: if (ec == boost::asio::error::eof) return; // In the following, remainder is the number of bytes that // remain // in the buffer. We need this in the body processing to make // sure // that the data remaining in the buffer is dealt with before // another call to get more data for the body is scheduled. fusion::tie(parsed_ok, remainder) = this->parse_headers( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), headers, get_body, callback, placeholders::error, placeholders::bytes_transferred)), bytes_transferred); if (!parsed_ok || indeterminate(parsed_ok)) return; if (!get_body) { // We short-circuit here because the user does not // want to get the body (in the case of a HEAD // request). this->body_promise.set_value(""); this->destination_promise.set_value(""); this->source_promise.set_value(""); this->part.assign('\0'); this->response_parser_.reset(); return; } if (callback) { // Here we deal with the spill-over data from the // headers processing. This means the headers data // has already been parsed appropriately and we're // looking to treat everything that remains in the // buffer. typename protocol_base::buffer_type::const_iterator begin = this->part_begin; typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, remainder); // We're setting the body promise here to an empty string // because // this can be used as a signaling mechanism for the user to // determine that the body is now ready for processing, even // though the callback is already provided. this->body_promise.set_value(""); // The invocation of the callback is synchronous to allow us // to // wait before scheduling another read. callback(make_iterator_range(begin, end), ec); delegate_->read_some( boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred))); } else { // Here we handle the body data ourself and append to an // ever-growing string buffer. this->parse_body( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred)), remainder); } return; case body: if (ec == boost::asio::error::eof || is_ssl_short_read_error) { // Here we're handling the case when the connection has been // closed from the server side, or at least that the end of // file // has been reached while reading the socket. This signals // the end // of the body processing chain. if (callback) { typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; std::advance(end, bytes_transferred); // We call the callback function synchronously passing the // error // condition (in this case, end of file) so that it can // handle // it appropriately. callback(make_iterator_range(begin, end), ec); } else { string_type body_string; std::swap(body_string, this->partial_parsed); body_string.append(this->part.begin(), bytes_transferred); if (this->is_chunk_encoding) this->body_promise.set_value(parse_chunk_encoding(body_string)); else this->body_promise.set_value(body_string); } // TODO set the destination value somewhere! this->destination_promise.set_value(""); this->source_promise.set_value(""); this->part.assign('\0'); this->response_parser_.reset(); this->timer_.cancel(); } else { // This means the connection has not been closed yet and we // want // to get more // data. if (callback) { // Here we have a body_handler callback. Let's invoke the // callback from here and make sure we're getting more // data // right after. typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); delegate_->read_some( boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred))); } else { // Here we don't have a body callback. Let's // make sure that we deal with the remainder // from the headers part in case we do have data // that's still in the buffer. this->parse_body( delegate_, request_strand_.wrap(boost::bind( &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred)), bytes_transferred); } } return; default: BOOST_ASSERT(false && "Bug, report this to the developers!"); } } else { boost::system::system_error error(is_timedout_ ? asio::error::timed_out : ec); this->source_promise.set_exception(boost::copy_exception(error)); this->destination_promise.set_exception(boost::copy_exception(error)); switch (state) { case version: this->version_promise.set_exception(boost::copy_exception(error)); case status: this->status_promise.set_exception(boost::copy_exception(error)); case status_message: this->status_message_promise.set_exception( boost::copy_exception(error)); case headers: this->headers_promise.set_exception(boost::copy_exception(error)); case body: if (!callback) { // N.B. if callback is non-null, then body_promise has // already been set to value "" to indicate body is // handled by streaming handler so no exception should be set this->body_promise.set_exception(boost::copy_exception(error)); } break; default: BOOST_ASSERT(false && "Bug, report this to the developers!"); } } } string_type parse_chunk_encoding(string_type& body_string) { string_type body; string_type crlf = "\r\n"; typename string_type::iterator begin = body_string.begin(); for (typename string_type::iterator iter = std::search(begin, body_string.end(), crlf.begin(), crlf.end()); iter != body_string.end(); iter = std::search(begin, body_string.end(), crlf.begin(), crlf.end())) { string_type line(begin, iter); if (line.empty()) break; std::stringstream stream(line); int len; stream >> std::hex >> len; std::advance(iter, 2); if (!len) break; if (len <= body_string.end() - iter) { body.insert(body.end(), iter, iter + len); std::advance(iter, len + 2); } begin = iter; } return body; } int timeout_; boost::asio::deadline_timer timer_; bool is_timedout_; bool follow_redirect_; resolver_type& resolver_; resolve_function resolve_; boost::asio::io_service::strand request_strand_; connection_delegate_ptr delegate_; boost::asio::streambuf command_streambuf; string_type method; }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/async_protocol_handler.hpp000066400000000000000000000350121256751517300332540ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ // Copyright 2010 (C) Dean Michael Berris // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { namespace impl { template struct http_async_protocol_handler { protected: typedef typename string::type string_type; #ifdef BOOST_NETWORK_DEBUG struct debug_escaper { string_type& string; explicit debug_escaper(string_type& string_) : string(string_) {} debug_escaper(debug_escaper const& other) : string(other.string) {} void operator()(typename string_type::value_type input) { if (!algorithm::is_print()(input)) { typename ostringstream::type escaped_stream; if (input == '\r') { string.append("\\r"); } else if (input == '\n') { string.append("\\n"); } else { escaped_stream << "\\x" << static_cast(input); string.append(escaped_stream.str()); } } else { string.push_back(input); } } }; #endif template void init_response(ResponseType& response_, bool get_body) { // TODO(dberris): review parameter necessity. (void)get_body; boost::shared_future source_future( source_promise.get_future()); source(response_, source_future); boost::shared_future destination_future( destination_promise.get_future()); destination(response_, destination_future); boost::shared_future::type> headers_future( headers_promise.get_future()); headers(response_, headers_future); boost::shared_future body_future(body_promise.get_future()); body(response_, body_future); boost::shared_future version_future( version_promise.get_future()); version(response_, version_future); boost::shared_future status_future( status_promise.get_future()); status(response_, status_future); boost::shared_future status_message_future( status_message_promise.get_future()); status_message(response_, status_message_future); } struct to_http_headers { typedef typename string::type string_type; template string_type const operator()(U const& pair) const { typedef typename ostringstream::type ostringstream_type; typedef constants constants; ostringstream_type header_line; header_line << pair.first << constants::colon() << constants::space() << pair.second << constants::crlf(); return header_line.str(); } }; template logic::tribool parse_version(Delegate& delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; part_begin = part.begin(); typename buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); typename boost::iterator_range result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_version_done, input_range); if (parsed_ok == true) { string_type version; std::swap(version, partial_parsed); version.append(boost::begin(result_range), boost::end(result_range)); algorithm::trim(version); version_promise.set_value(version); part_begin = boost::end(result_range); } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG string_type escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); BOOST_NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\""); #endif std::runtime_error error("Invalid Version Part."); version_promise.set_exception(boost::copy_exception(error)); status_promise.set_exception(boost::copy_exception(error)); status_message_promise.set_exception(boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback); } return parsed_ok; } template logic::tribool parse_status(Delegate& delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; typename buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); typename boost::iterator_range result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_status_done, input_range); if (parsed_ok == true) { string_type status; std::swap(status, partial_parsed); status.append(boost::begin(result_range), boost::end(result_range)); trim(status); boost::uint16_t status_int = lexical_cast(status); status_promise.set_value(status_int); part_begin = boost::end(result_range); } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG string_type escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); BOOST_NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\""); #endif std::runtime_error error("Invalid status part."); status_promise.set_exception(boost::copy_exception(error)); status_message_promise.set_exception(boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback); } return parsed_ok; } template logic::tribool parse_status_message(Delegate& delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; typename buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); typename boost::iterator_range result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_status_message_done, input_range); if (parsed_ok == true) { string_type status_message; std::swap(status_message, partial_parsed); status_message.append(boost::begin(result_range), boost::end(result_range)); algorithm::trim(status_message); status_message_promise.set_value(status_message); part_begin = boost::end(result_range); } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG string_type escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); BOOST_NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\""); #endif std::runtime_error error("Invalid status message part."); status_message_promise.set_exception(boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback); } return parsed_ok; } void parse_headers_real(string_type& headers_part) { typename boost::iterator_range input_range = boost::make_iterator_range(headers_part), result_range; logic::tribool parsed_ok; response_parser_type headers_parser( response_parser_type::http_header_line_done); typename headers_container::type headers; std::pair header_pair; while (!boost::empty(input_range)) { fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( response_parser_type::http_header_colon, input_range); if (headers_parser.state() != response_parser_type::http_header_colon) break; header_pair.first = string_type(boost::begin(result_range), boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( response_parser_type::http_header_line_done, input_range); header_pair.second = string_type(boost::begin(result_range), boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); trim(header_pair.first); if (header_pair.first.size() > 1) { header_pair.first.erase(header_pair.first.size() - 1); } trim(header_pair.second); headers.insert(header_pair); } // determine if the body parser will need to handle chunked encoding typename headers_range >::type transfer_encoding_range = headers.equal_range("Transfer-Encoding"); is_chunk_encoding = !boost::empty(transfer_encoding_range) && boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked"); headers_promise.set_value(headers); } template fusion::tuple parse_headers(Delegate& delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; typename buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); typename boost::iterator_range result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_headers_done, input_range); if (parsed_ok == true) { string_type headers_string; std::swap(headers_string, partial_parsed); headers_string.append(boost::begin(result_range), boost::end(result_range)); part_begin = boost::end(result_range); this->parse_headers_real(headers_string); } else if (parsed_ok == false) { // We want to output the contents of the buffer that caused // the error in debug builds. #ifdef BOOST_NETWORK_DEBUG string_type escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); BOOST_NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\" consumed length: " << boost::distance(result_range)); #endif std::runtime_error error("Invalid header part."); headers_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback); } return fusion::make_tuple( parsed_ok, std::distance(boost::end(result_range), part_end)); } template void parse_body(Delegate& delegate_, Callback callback, size_t bytes) { // TODO: we should really not use a string for the partial body // buffer. partial_parsed.append(part_begin, bytes); part_begin = part.begin(); delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback); } typedef response_parser response_parser_type; // TODO: make 1024 go away and become a configurable value. typedef boost::array::type, 1024> buffer_type; response_parser_type response_parser_; boost::promise version_promise; boost::promise status_promise; boost::promise status_message_promise; boost::promise::type> headers_promise; boost::promise source_promise; boost::promise destination_promise; boost::promise body_promise; buffer_type part; typename buffer_type::const_iterator part_begin; string_type partial_parsed; bool is_chunk_encoding; }; } /* impl */ } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/connection_delegate.hpp000066400000000000000000000022651256751517300325160ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { namespace impl { struct connection_delegate { virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, function handler) = 0; virtual void write( asio::streambuf &command_streambuf, function handler) = 0; virtual void read_some( asio::mutable_buffers_1 const &read_buffer, function handler) = 0; virtual void disconnect() = 0; virtual ~connection_delegate() {} }; } /* impl */ } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ \ */ connection_delegate_factory.hpp000066400000000000000000000042551256751517300341670ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #ifdef BOOST_NETWORK_ENABLE_HTTPS #include #endif /* BOOST_NETWORK_ENABLE_HTTPS */ namespace boost { namespace network { namespace http { namespace impl { struct ssl_delegate; struct normal_delegate; template struct connection_delegate_factory { typedef shared_ptr connection_delegate_ptr; typedef typename string::type string_type; // This is the factory method that actually returns the delegate // instance. // TODO Support passing in proxy settings when crafting connections. static connection_delegate_ptr new_connection_delegate( asio::io_service& service, bool https, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, long ssl_options) { connection_delegate_ptr delegate; if (https) { #ifdef BOOST_NETWORK_ENABLE_HTTPS delegate.reset(new ssl_delegate( service, always_verify_peer, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); #else BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported.")); #endif /* BOOST_NETWORK_ENABLE_HTTPS */ } else { delegate.reset(new normal_delegate(service)); } return delegate; } }; } /* impl */ } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/normal_delegate.hpp000066400000000000000000000033141256751517300316430ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { namespace impl { struct normal_delegate : connection_delegate { normal_delegate(asio::io_service &service); virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, function handler); virtual void write( asio::streambuf &command_streambuf, function handler); virtual void read_some( asio::mutable_buffers_1 const &read_buffer, function handler); virtual void disconnect(); ~normal_delegate(); private: asio::io_service &service_; scoped_ptr socket_; normal_delegate(normal_delegate const &); // = delete normal_delegate &operator=(normal_delegate); // = delete }; } /* impl */ } /* http */ } /* network */ } /* boost */ #ifdef BOOST_NETWORK_NO_LIB #include #endif /* BOOST_NETWORK_NO_LIB */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/normal_delegate.ipp000066400000000000000000000041071256751517300316450ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include boost::network::http::impl::normal_delegate::normal_delegate( asio::io_service &service) : service_(service) {} void boost::network::http::impl::normal_delegate::connect( asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, function handler) { // TODO(dberris): review parameter necessity. (void)host; socket_.reset(new asio::ip::tcp::socket(service_, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), source_port))); socket_->async_connect(endpoint, handler); } void boost::network::http::impl::normal_delegate::write( asio::streambuf &command_streambuf, function handler) { asio::async_write(*socket_, command_streambuf, handler); } void boost::network::http::impl::normal_delegate::read_some( asio::mutable_buffers_1 const &read_buffer, function handler) { socket_->async_read_some(read_buffer, handler); } void boost::network::http::impl::normal_delegate::disconnect() { if (socket_.get() && socket_->is_open()) { boost::system::error_code ignored; socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (!ignored) { socket_->close(ignored); } } } boost::network::http::impl::normal_delegate::~normal_delegate() {} #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/ssl_delegate.hpp000066400000000000000000000053051256751517300311560ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { namespace impl { struct ssl_delegate : connection_delegate, enable_shared_from_this { ssl_delegate(asio::io_service &service, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, long ssl_options); virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, function handler); virtual void write( asio::streambuf &command_streambuf, function handler); virtual void read_some( asio::mutable_buffers_1 const &read_buffer, function handler); virtual void disconnect(); ~ssl_delegate(); private: asio::io_service &service_; optional certificate_filename_; optional verify_path_; optional certificate_file_; optional private_key_file_; optional ciphers_; long ssl_options_; scoped_ptr context_; scoped_ptr tcp_socket_; scoped_ptr > socket_; bool always_verify_peer_; ssl_delegate(ssl_delegate const &); // = delete ssl_delegate &operator=(ssl_delegate); // = delete void handle_connected(system::error_code const &ec, function handler); }; } /* impl */ } /* http */ } /* network */ } /* boost */ #ifdef BOOST_NETWORK_NO_LIB #include #endif /* BOOST_NETWORK_NO_LIB */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/ssl_delegate.ipp000066400000000000000000000104401256751517300311530ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include boost::network::http::impl::ssl_delegate::ssl_delegate( asio::io_service &service, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, long ssl_options) : service_(service), certificate_filename_(certificate_filename), verify_path_(verify_path), certificate_file_(certificate_file), private_key_file_(private_key_file), ciphers_(ciphers), ssl_options_(ssl_options), always_verify_peer_(always_verify_peer) {} void boost::network::http::impl::ssl_delegate::connect( asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, function handler) { context_.reset( new asio::ssl::context(service_, asio::ssl::context::sslv23_client)); if (ciphers_) { ::SSL_CTX_set_cipher_list(context_->native_handle(), ciphers_->c_str()); } if (ssl_options_ != 0) { context_->set_options(ssl_options_); } if (certificate_filename_ || verify_path_) { context_->set_verify_mode(asio::ssl::context::verify_peer); if (certificate_filename_) context_->load_verify_file(*certificate_filename_); if (verify_path_) context_->add_verify_path(*verify_path_); } else { if (always_verify_peer_) { context_->set_verify_mode(asio::ssl::context::verify_peer); // use openssl default verify paths. uses openssl environment variables // SSL_CERT_DIR, SSL_CERT_FILE context_->set_default_verify_paths(); } else context_->set_verify_mode(asio::ssl::context::verify_none); } if (certificate_file_) context_->use_certificate_file(*certificate_file_, boost::asio::ssl::context::pem); if (private_key_file_) context_->use_private_key_file(*private_key_file_, boost::asio::ssl::context::pem); tcp_socket_.reset(new asio::ip::tcp::socket(service_, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), source_port))); socket_.reset( new asio::ssl::stream(*(tcp_socket_.get()), *context_)); if (always_verify_peer_) socket_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); socket_->lowest_layer().async_connect( endpoint, ::boost::bind( &boost::network::http::impl::ssl_delegate::handle_connected, boost::network::http::impl::ssl_delegate::shared_from_this(), asio::placeholders::error, handler)); } void boost::network::http::impl::ssl_delegate::handle_connected( system::error_code const &ec, function handler) { if (!ec) { socket_->async_handshake(asio::ssl::stream_base::client, handler); } else { handler(ec); } } void boost::network::http::impl::ssl_delegate::write( asio::streambuf &command_streambuf, function handler) { asio::async_write(*socket_, command_streambuf, handler); } void boost::network::http::impl::ssl_delegate::read_some( asio::mutable_buffers_1 const &read_buffer, function handler) { socket_->async_read_some(read_buffer, handler); } void boost::network::http::impl::ssl_delegate::disconnect() { if (socket_.get() && socket_->lowest_layer().is_open()) { boost::system::error_code ignored; socket_->lowest_layer().shutdown( boost::asio::ip::tcp::socket::shutdown_both, ignored); if (!ignored) { socket_->lowest_layer().close(ignored); } } } boost::network::http::impl::ssl_delegate::~ssl_delegate() {} #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/sync_base.hpp000066400000000000000000000305441256751517300304740ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 // Copyright 2013 Google, Inc. // Copyright 2009 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_NETWORK_ENABLE_HTTPS #include #endif namespace boost { namespace network { namespace http { namespace impl { template struct sync_connection_base_impl { protected: typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; typedef function resolver_function_type; template void init_socket(Socket& socket_, resolver_type& resolver_, string_type const& hostname, string_type const& port, resolver_function_type resolve_) { using boost::asio::ip::tcp; boost::system::error_code error = boost::asio::error::host_not_found; typename resolver_type::iterator endpoint_iterator, end; boost::tie(endpoint_iterator, end) = resolve_(resolver_, hostname, port); while (error && endpoint_iterator != end) { socket_.close(); socket_.connect(tcp::endpoint(endpoint_iterator->endpoint().address(), endpoint_iterator->endpoint().port()), error); ++endpoint_iterator; } if (error) throw boost::system::system_error(error); } template void read_status(Socket& socket_, basic_response& response_, boost::asio::streambuf& response_buffer) { boost::asio::read_until(socket_, response_buffer, "\r\n"); std::istream response_stream(&response_buffer); string_type http_version; unsigned int status_code; string_type status_message; response_stream >> http_version >> status_code; std::getline(response_stream, status_message); trim_left(status_message); trim_right_if(status_message, boost::is_space() || boost::is_any_of("\r")); if (!response_stream || http_version.substr(0, 5) != "HTTP/") throw std::runtime_error("Invalid response"); response_ << http::version(http_version) << http::status(status_code) << http::status_message(status_message); } template void read_headers(Socket& socket_, basic_response& response_, boost::asio::streambuf& response_buffer) { boost::asio::read_until(socket_, response_buffer, "\r\n\r\n"); std::istream response_stream(&response_buffer); string_type header_line, name; while (std::getline(response_stream, header_line) && header_line != "\r") { trim_right_if(header_line, boost::is_space() || boost::is_any_of("\r")); typename string_type::size_type colon_offset; if (header_line.size() && header_line[0] == ' ') { assert(!name.empty()); if (name.empty()) throw std::runtime_error(std::string("Malformed header: ") + header_line); response_ << header(name, trim_left_copy(header_line)); } else if ((colon_offset = header_line.find_first_of(':')) != string_type::npos) { name = header_line.substr(0, colon_offset); response_ << header(name, header_line.substr(colon_offset + 2)); } } } template void send_request_impl(Socket& socket_, string_type const& method, boost::asio::streambuf& request_buffer) { // TODO(dberris): review parameter necessity. (void)method; write(socket_, request_buffer); } template void read_body_normal(Socket& socket_, basic_response& response_, boost::asio::streambuf& response_buffer, typename ostringstream::type& body_stream) { // TODO(dberris): review parameter necessity. (void)response_; boost::system::error_code error; if (response_buffer.size() > 0) body_stream << &response_buffer; while (boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error)) { body_stream << &response_buffer; } } template void read_body_transfer_chunk_encoding( Socket& socket_, basic_response& response_, boost::asio::streambuf& response_buffer, typename ostringstream::type& body_stream) { boost::system::error_code error; // look for the content-length header typename headers_range >::type content_length_range = headers(response_)["Content-Length"]; if (boost::empty(content_length_range)) { typename headers_range >::type transfer_encoding_range = headers(response_)["Transfer-Encoding"]; if (boost::empty(transfer_encoding_range)) { read_body_normal(socket_, response_, response_buffer, body_stream); return; } if (boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { bool stopping = false; do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); std::size_t chunk_size = 0; string_type data; { std::istream chunk_stream(&response_buffer); std::getline(chunk_stream, data); typename istringstream::type chunk_size_stream(data); chunk_size_stream >> std::hex >> chunk_size; } if (chunk_size == 0) { stopping = true; if (!read_until(socket_, response_buffer, "\r\n", error) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); } else { bool stopping_inner = false; do { if (response_buffer.size() < (chunk_size + 2)) { std::size_t bytes_to_read = (chunk_size + 2) - response_buffer.size(); std::size_t chunk_bytes_read = read(socket_, response_buffer, boost::asio::transfer_at_least(bytes_to_read), error); if (chunk_bytes_read == 0) { if (error != boost::asio::error::eof) throw boost::system::system_error(error); stopping_inner = true; } } std::istreambuf_iterator eos; std::istreambuf_iterator stream_iterator(&response_buffer); for (; chunk_size > 0 && stream_iterator != eos; --chunk_size) body_stream << *stream_iterator++; response_buffer.consume(2); } while (!stopping_inner && chunk_size != 0); if (chunk_size != 0) throw std::runtime_error( "Size mismatch between tranfer encoding chunk data " "size and declared chunk size."); } } while (!stopping); } else throw std::runtime_error("Unsupported Transfer-Encoding."); } else { size_t already_read = response_buffer.size(); if (already_read) body_stream << &response_buffer; size_t length = lexical_cast(boost::begin(content_length_range)->second) - already_read; if (length == 0) return; size_t bytes_read = 0; while ((bytes_read = boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error))) { body_stream << &response_buffer; length -= bytes_read; if ((length <= 0) || error) break; } } } template void read_body(Socket& socket_, basic_response& response_, boost::asio::streambuf& response_buffer) { typename ostringstream::type body_stream; // TODO tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1 if (version_major == 1 && version_minor == 0) { read_body_normal(socket_, response_, response_buffer, body_stream); } else if (version_major == 1 && version_minor == 1) { if (response_.version() == "HTTP/1.0") read_body_normal(socket_, response_, response_buffer, body_stream); else read_body_transfer_chunk_encoding(socket_, response_, response_buffer, body_stream); } else { throw std::runtime_error("Unsupported HTTP version number."); } response_ << network::body(body_stream.str()); } }; template struct sync_connection_base { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; typedef function resolver_function_type; typedef function body_generator_function_type; // FIXME make the certificate filename and verify path parameters be // optional // ranges static sync_connection_base* new_connection( resolver_type& resolver, resolver_function_type resolve, bool https, bool always_verify_peer, int timeout, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) { if (https) { #ifdef BOOST_NETWORK_ENABLE_HTTPS return dynamic_cast< sync_connection_base*>( new https_sync_connection( resolver, resolve, always_verify_peer, timeout, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); #else throw std::runtime_error("HTTPS not supported."); #endif } return dynamic_cast< sync_connection_base*>( new http_sync_connection( resolver, resolve, timeout)); } virtual void init_socket(string_type const& hostname, string_type const& port) = 0; virtual void send_request_impl(string_type const& method, basic_request const& request_, body_generator_function_type generator) = 0; virtual void read_status(basic_response& response_, boost::asio::streambuf& response_buffer) = 0; virtual void read_headers(basic_response& response_, boost::asio::streambuf& response_buffer) = 0; virtual void read_body(basic_response& response_, boost::asio::streambuf& response_buffer) = 0; virtual bool is_open() = 0; virtual void close_socket() = 0; virtual ~sync_connection_base() {} protected: sync_connection_base() {} }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/sync_normal.hpp000066400000000000000000000115531256751517300310510ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 // Copyright 2013 Google, Inc. // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { namespace impl { template struct sync_connection_base_impl; template struct sync_connection_base; template struct http_sync_connection : public virtual sync_connection_base, sync_connection_base_impl, boost::enable_shared_from_this< http_sync_connection > { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; typedef function resolver_function_type; typedef http_sync_connection this_type; typedef sync_connection_base_impl connection_base; typedef function body_generator_function_type; http_sync_connection(resolver_type& resolver, resolver_function_type resolve, int timeout) : connection_base(), timeout_(timeout), timer_(resolver.get_io_service()), resolver_(resolver), resolve_(resolve), socket_(resolver.get_io_service()) {} void init_socket(string_type const& hostname, string_type const& port) { connection_base::init_socket(socket_, resolver_, hostname, port, resolve_); } void send_request_impl(string_type const& method, basic_request const& request_, body_generator_function_type generator) { boost::asio::streambuf request_buffer; linearize( request_, method, version_major, version_minor, std::ostreambuf_iterator::type>(&request_buffer)); connection_base::send_request_impl(socket_, method, request_buffer); if (generator) { string_type chunk; while (generator(chunk)) { std::copy(chunk.begin(), chunk.end(), std::ostreambuf_iterator::type>( &request_buffer)); chunk.clear(); connection_base::send_request_impl(socket_, method, request_buffer); } } if (timeout_ > 0) { timer_.expires_from_now(boost::posix_time::seconds(timeout_)); timer_.async_wait(boost::bind(&this_type::handle_timeout, this_type::shared_from_this(), boost::arg<1>())); } } void read_status(basic_response& response_, boost::asio::streambuf& response_buffer) { connection_base::read_status(socket_, response_, response_buffer); } void read_headers(basic_response& response, boost::asio::streambuf& response_buffer) { connection_base::read_headers(socket_, response, response_buffer); } void read_body(basic_response& response_, boost::asio::streambuf& response_buffer) { connection_base::read_body(socket_, response_, response_buffer); typename headers_range >::type connection_range = headers(response_)["Connection"]; if (version_major == 1 && version_minor == 1 && !boost::empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { close_socket(); } else if (version_major == 1 && version_minor == 0) { close_socket(); } } bool is_open() { return socket_.is_open(); } void close_socket() { timer_.cancel(); if (!is_open()) return; boost::system::error_code ignored; socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (ignored) return; socket_.close(ignored); } private: void handle_timeout(boost::system::error_code const& ec) { if (!ec) close_socket(); } int timeout_; boost::asio::deadline_timer timer_; resolver_type& resolver_; resolver_function_type resolve_; boost::asio::ip::tcp::socket socket_; }; } // namespace impl } // nmaespace http } // namespace network } // nmaespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/connection/sync_ssl.hpp000066400000000000000000000162051256751517300303610ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 // Copyright 2013 Google, Inc. // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { namespace impl { template struct sync_connection_base_impl; template struct sync_connection_base; template struct https_sync_connection : public virtual sync_connection_base, sync_connection_base_impl, boost::enable_shared_from_this< https_sync_connection > { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; typedef function resolver_function_type; typedef https_sync_connection this_type; typedef sync_connection_base_impl connection_base; typedef function body_generator_function_type; // FIXME make the certificate filename and verify path parameters be // optional ranges https_sync_connection( resolver_type& resolver, resolver_function_type resolve, bool always_verify_peer, int timeout, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) : connection_base(), timeout_(timeout), timer_(resolver.get_io_service()), resolver_(resolver), resolve_(resolve), context_(resolver.get_io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.get_io_service(), context_) { if (ciphers) { ::SSL_CTX_set_cipher_list(context_.native_handle(), ciphers->c_str()); } if (ssl_options != 0) { context_.set_options(ssl_options); } if (certificate_filename || verify_path) { context_.set_verify_mode(boost::asio::ssl::context::verify_peer); // FIXME make the certificate filename and verify path parameters // be // optional ranges if (certificate_filename) context_.load_verify_file(*certificate_filename); if (verify_path) context_.add_verify_path(*verify_path); } else { if (always_verify_peer) context_.set_verify_mode(boost::asio::ssl::context_base::verify_peer); else context_.set_verify_mode(boost::asio::ssl::context_base::verify_none); } if (certificate_file) context_.use_certificate_file(*certificate_file, boost::asio::ssl::context::pem); if (private_key_file) context_.use_private_key_file(*private_key_file, boost::asio::ssl::context::pem); } void init_socket(string_type const& hostname, string_type const& port) { connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_); socket_.handshake(boost::asio::ssl::stream_base::client); } void send_request_impl(string_type const& method, basic_request const& request_, body_generator_function_type generator) { boost::asio::streambuf request_buffer; linearize( request_, method, version_major, version_minor, std::ostreambuf_iterator::type>(&request_buffer)); connection_base::send_request_impl(socket_, method, request_buffer); if (generator) { string_type chunk; while (generator(chunk)) { std::copy(chunk.begin(), chunk.end(), std::ostreambuf_iterator::type>( &request_buffer)); chunk.clear(); connection_base::send_request_impl(socket_, method, request_buffer); } } if (timeout_ > 0) { timer_.expires_from_now(boost::posix_time::seconds(timeout_)); timer_.async_wait(boost::bind(&this_type::handle_timeout, this_type::shared_from_this(), boost::arg<1>())); } } void read_status(basic_response& response_, boost::asio::streambuf& response_buffer) { connection_base::read_status(socket_, response_, response_buffer); } void read_headers(basic_response& response_, boost::asio::streambuf& response_buffer) { connection_base::read_headers(socket_, response_, response_buffer); } void read_body(basic_response& response_, boost::asio::streambuf& response_buffer) { connection_base::read_body(socket_, response_, response_buffer); typename headers_range >::type connection_range = headers(response_)["Connection"]; if (version_major == 1 && version_minor == 1 && !boost::empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { close_socket(); } else if (version_major == 1 && version_minor == 0) { close_socket(); } } bool is_open() { return socket_.lowest_layer().is_open(); } void close_socket() { timer_.cancel(); boost::system::error_code ignored; socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (ignored) return; socket_.lowest_layer().close(ignored); } ~https_sync_connection() { close_socket(); } private: void handle_timeout(boost::system::error_code const& ec) { if (!ec) close_socket(); } int timeout_; boost::asio::deadline_timer timer_; resolver_type& resolver_; resolver_function_type resolve_; boost::asio::ssl::context context_; boost::asio::ssl::stream socket_; }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/facade.hpp000066400000000000000000000156511256751517300255740ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 // Copyright 2013 Google, Inc. // Copyright 2010 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; template struct basic_response; template struct basic_client_facade { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; typedef basic_client_impl pimpl_type; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; explicit basic_client_facade(client_options const& options) { init_pimpl(options); } ~basic_client_facade() { pimpl->wait_complete(); } response head(request const& request) { return pimpl->request_skeleton(request, "HEAD", false, body_callback_function_type(), body_generator_function_type()); } response get(request const& request, body_callback_function_type body_handler = body_callback_function_type()) { return pimpl->request_skeleton(request, "GET", true, body_handler, body_generator_function_type()); } response post(request request, string_type const& body = string_type(), string_type const& content_type = string_type(), body_callback_function_type body_handler = body_callback_function_type(), body_generator_function_type body_generator = body_generator_function_type()) { if (body != string_type()) { request << remove_header("Content-Length") << header("Content-Length", boost::lexical_cast(body.size())) << boost::network::body(body); } typename headers_range >::type content_type_headers = headers(request)["Content-Type"]; if (content_type != string_type()) { if (!boost::empty(content_type_headers)) request << remove_header("Content-Type"); request << header("Content-Type", content_type); } else { if (boost::empty(content_type_headers)) { typedef typename char_::type char_type; static char_type content_type[] = "x-application/octet-stream"; request << header("Content-Type", content_type); } } return pimpl->request_skeleton(request, "POST", true, body_handler, body_generator); } response post(request const& request, body_generator_function_type body_generator, body_callback_function_type callback = body_generator_function_type()) { return pimpl->request_skeleton(request, "POST", true, callback, body_generator); } response post(request const& request, body_callback_function_type callback, body_generator_function_type body_generator = body_generator_function_type()) { return post(request, string_type(), string_type(), callback, body_generator); } response post(request const& request, string_type const& body, body_callback_function_type callback, body_generator_function_type body_generator = body_generator_function_type()) { return post(request, body, string_type(), callback, body_generator); } response put(request request, string_type const& body = string_type(), string_type const& content_type = string_type(), body_callback_function_type body_handler = body_callback_function_type(), body_generator_function_type body_generator = body_generator_function_type()) { if (body != string_type()) { request << remove_header("Content-Length") << header("Content-Length", boost::lexical_cast(body.size())) << boost::network::body(body); } typename headers_range >::type content_type_headers = headers(request)["Content-Type"]; if (content_type != string_type()) { if (!boost::empty(content_type_headers)) request << remove_header("Content-Type"); request << header("Content-Type", content_type); } else { if (boost::empty(content_type_headers)) { typedef typename char_::type char_type; static char_type content_type[] = "x-application/octet-stream"; request << header("Content-Type", content_type); } } return pimpl->request_skeleton(request, "PUT", true, body_handler, body_generator); } response put(request const& request, body_callback_function_type callback, body_generator_function_type body_generator = body_generator_function_type()) { return put(request, string_type(), string_type(), callback, body_generator); } response put(request const& request, string_type body, body_callback_function_type callback, body_generator_function_type body_generator = body_generator_function_type()) { return put(request, body, string_type(), callback, body_generator); } response delete_(request const& request, body_callback_function_type body_handler = body_callback_function_type()) { return pimpl->request_skeleton(request, "DELETE", true, body_handler, body_generator_function_type()); } void clear_resolved_cache() { pimpl->clear_resolved_cache(); } protected: boost::shared_ptr pimpl; void init_pimpl(client_options const& options) { pimpl.reset(new pimpl_type( options.cache_resolved(), options.follow_redirects(), options.always_verify_peer(), options.openssl_certificate(), options.openssl_verify_path(), options.openssl_certificate_file(), options.openssl_private_key_file(), options.openssl_ciphers(), options.openssl_options(), options.io_service(), options.timeout())); } }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/macros.hpp000066400000000000000000000015141256751517300256460ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 // Copyright 2011 Dean Michael Berris . // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK #define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, \ error_name) \ void function_name(boost::iterator_range const& range_name, \ boost::system::error_code const& error_name) #endif #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/options.hpp000066400000000000000000000121021256751517300260500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128 #include #include #include #include // Copyright 2013 Google, Inc. // Copyright 2013 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct client_options { typedef typename string::type string_type; client_options() : cache_resolved_(false), follow_redirects_(false), openssl_certificate_(), openssl_verify_path_(), openssl_certificate_file_(), openssl_private_key_file_(), openssl_ciphers_(), openssl_options_(0), io_service_(), always_verify_peer_(false), timeout_(0) {} client_options(client_options const& other) : cache_resolved_(other.cache_resolved_), follow_redirects_(other.follow_redirects_), openssl_certificate_(other.openssl_certificate_), openssl_verify_path_(other.openssl_verify_path_), openssl_certificate_file_(other.openssl_certificate_file_), openssl_private_key_file_(other.openssl_private_key_file_), openssl_ciphers_(other.openssl_ciphers_), openssl_options_(other.openssl_options_), io_service_(other.io_service_), always_verify_peer_(other.always_verify_peer_), timeout_(other.timeout_) {} client_options& operator=(client_options other) { other.swap(*this); return *this; } void swap(client_options& other) { using std::swap; swap(cache_resolved_, other.cache_resolved_); swap(follow_redirects_, other.follow_redirects_); swap(openssl_certificate_, other.openssl_certificate_); swap(openssl_verify_path_, other.openssl_verify_path_); swap(openssl_certificate_file_, other.openssl_certificate_file_); swap(openssl_private_key_file_, other.openssl_private_key_file_); swap(openssl_ciphers_, other.openssl_ciphers_); swap(openssl_options_, other.openssl_options_); swap(io_service_, other.io_service_); swap(always_verify_peer_, other.always_verify_peer_); swap(timeout_, other.timeout_); } client_options& cache_resolved(bool v) { cache_resolved_ = v; return *this; } client_options& follow_redirects(bool v) { follow_redirects_ = v; return *this; } client_options& openssl_certificate(string_type const& v) { openssl_certificate_ = v; return *this; } client_options& openssl_verify_path(string_type const& v) { openssl_verify_path_ = v; return *this; } client_options& openssl_certificate_file(string_type const& v) { openssl_certificate_file_ = v; return *this; } client_options& openssl_private_key_file(string_type const& v) { openssl_private_key_file_ = v; return *this; } client_options& openssl_ciphers(string_type const& v) { openssl_ciphers_ = v; return *this; } client_options& openssl_options(long o) { openssl_options_ = o; return *this; } client_options& io_service(boost::shared_ptr v) { io_service_ = v; return *this; } client_options& always_verify_peer(bool v) { always_verify_peer_ = v; return *this; } client_options& timeout(int v) { timeout_ = v; return *this; } bool cache_resolved() const { return cache_resolved_; } bool follow_redirects() const { return follow_redirects_; } boost::optional openssl_certificate() const { return openssl_certificate_; } boost::optional openssl_verify_path() const { return openssl_verify_path_; } boost::optional openssl_certificate_file() const { return openssl_certificate_file_; } boost::optional openssl_private_key_file() const { return openssl_private_key_file_; } boost::optional openssl_ciphers() const { return openssl_ciphers_; } long openssl_options() const { return openssl_options_; } boost::shared_ptr io_service() const { return io_service_; } bool always_verify_peer() const { return always_verify_peer_; } int timeout() const { return timeout_; } private: bool cache_resolved_; bool follow_redirects_; boost::optional openssl_certificate_; boost::optional openssl_verify_path_; boost::optional openssl_certificate_file_; boost::optional openssl_private_key_file_; boost::optional openssl_ciphers_; long openssl_options_; boost::shared_ptr io_service_; bool always_verify_peer_; int timeout_; }; template inline void swap(client_options& a, client_options& b) { a.swap(b); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/client/pimpl.hpp000066400000000000000000000062041256751517300255040ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_client_impl; namespace impl { template struct async_client; template struct sync_client; template struct client_base { typedef unsupported_tag type; }; template struct client_base >::type> { typedef async_client type; }; template struct client_base >::type> { typedef sync_client type; }; } // namespace impl template struct basic_client; template struct basic_client_impl : impl::client_base::type { BOOST_STATIC_ASSERT( (mpl::not_, is_sync > >::value)); typedef typename impl::client_base::type base_type; typedef typename base_type::string_type string_type; basic_client_impl(bool cache_resolved, bool follow_redirect, bool always_verify_peer, optional const& certificate_filename, optional const& verify_path, optional const& certificate_file, optional const& private_key_file, optional const& ciphers, long ssl_options, boost::shared_ptr service, int timeout) : base_type(cache_resolved, follow_redirect, always_verify_peer, timeout, service, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options) {} ~basic_client_impl() {} }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 cpp-netlib-0.11.2-final/boost/network/protocol/http/client/sync_impl.hpp000066400000000000000000000077341256751517300263710ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 #include #include #include #include #include #include #include #include #include // Copyright 2013 Google, Inc. // Copyright 2010 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_client_impl; namespace impl { template struct sync_client : connection_policy::type { typedef typename string::type string_type; typedef typename connection_policy::type connection_base; typedef typename resolver::type resolver_type; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; friend struct basic_client_impl; boost::shared_ptr service_ptr; boost::asio::io_service& service_; resolver_type resolver_; optional certificate_filename_; optional verify_path_; optional certificate_file_; optional private_key_file_; optional ciphers_; long ssl_options_; bool always_verify_peer_; sync_client( bool cache_resolved, bool follow_redirect, bool always_verify_peer, int timeout, boost::shared_ptr service, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) : connection_base(cache_resolved, follow_redirect, timeout), service_ptr(service.get() ? service : make_shared()), service_(*service_ptr), resolver_(service_), certificate_filename_(certificate_filename), verify_path_(verify_path), certificate_file_(certificate_file), private_key_file_(private_key_file), ciphers_(ciphers), ssl_options_(ssl_options), always_verify_peer_(always_verify_peer) {} ~sync_client() { connection_base::cleanup(); service_ptr.reset(); } void wait_complete() {} basic_response request_skeleton(basic_request const& request_, string_type method, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { typename connection_base::connection_ptr connection_; connection_ = connection_base::get_connection( resolver_, request_, always_verify_peer_, certificate_filename_, verify_path_, certificate_file_, private_key_file_, ciphers_); return connection_->send_request(method, request_, get_body, callback, generator); } }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 cpp-netlib-0.11.2-final/boost/network/protocol/http/errors.hpp000066400000000000000000000014461256751517300244240ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007, 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP__ #define __NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP__ #include #include namespace boost { namespace network { namespace http { namespace errors { template struct connection_timeout_exception : std::runtime_error {}; typedef connection_timeout_exception<> connection_timeout; } // namespace errors } // namespace http } // namespace network } // namespace boost #endif // __NETWORK_PROTOCOL_HTTP_20080516_HPP__ cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/000077500000000000000000000000001256751517300233335ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/message.ipp000066400000000000000000000230431256751517300254730ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_IPP #include #include #include #include namespace boost { namespace network { namespace http { // static member functions of boost::network::http::message template typename message_impl::string_type const message_impl::url_decode( typename message_impl::string_type const &str) { char decode_buf[3]; typename message_impl::string_type result; result.reserve(str.size()); for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { switch (str[pos]) { case '+': // convert to space character result += ' '; break; case '%': // decode hexidecimal value if (pos + 2 < str.size()) { decode_buf[0] = str[++pos]; decode_buf[1] = str[++pos]; decode_buf[2] = '\0'; result += static_cast(strtol(decode_buf, 0, 16)); } else { // recover from error by not decoding character result += '%'; } break; default: // character does not need to be escaped result += str[pos]; } }; return result; } template typename message_impl::string_type const message_impl::url_encode( typename message_impl::string_type const &str) { char encode_buf[4]; typename message_impl::string_type result; encode_buf[0] = '%'; result.reserve(str.size()); // character selection for this algorithm is based on the following url: // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { switch (str[pos]) { default: if (str[pos] >= 32 && str[pos] < 127) { // character does not need to be escaped result += str[pos]; break; } // else pass through to next case case '$': case '&': case '+': case ',': case '/': case ':': case ';': case '=': case '?': case '@': case '"': case '<': case '>': case '#': case '%': case '{': case '}': case '|': case '\\': case '^': case '~': case '[': case ']': case '`': // the character needs to be encoded sprintf(encode_buf + 1, "%02X", str[pos]); result += encode_buf; break; } }; return result; } template typename message_impl::string_type const message_impl::make_query_string( typename query_container::type const &query_params) { typename message_impl::string_type query_string; for (typename query_container::type::const_iterator i = query_params.begin(); i != query_params.end(); ++i) { if (i != query_params.begin()) query_string += '&'; query_string += url_encode(i->first); query_string += '='; query_string += url_encode(i->second); } return query_string; } template typename message_impl::string_type const message_impl::make_set_cookie_header( typename message_impl::string_type const &name, typename message_impl::string_type const &value, typename message_impl::string_type const &path, bool const has_max_age, unsigned long const max_age) { typename message_impl::string_type set_cookie_header(name); set_cookie_header += "=\""; set_cookie_header += value; set_cookie_header += "\"; Version=\"1\""; if (!path.empty()) { set_cookie_header += "; Path=\""; set_cookie_header += path; set_cookie_header += '\"'; } if (has_max_age) { set_cookie_header += "; Max-Age=\""; set_cookie_header += boost::lexical_cast::string_type>(max_age); set_cookie_header += '\"'; } return set_cookie_header; } template bool message_impl::base64_decode( const typename message_impl::string_type &input, typename message_impl::string_type &output) { static const char nop = -1; static const char decoding_data[] = { nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop}; unsigned int input_length = input.size(); const char *input_ptr = input.data(); // allocate space for output string output.clear(); output.reserve(((input_length + 2) / 3) * 4); // for each 4-bytes sequence from the input, extract 4 6-bits sequences // by droping first two bits // and regenerate into 3 8-bits sequence for (unsigned int i = 0; i < input_length; i++) { char base64code0; char base64code1; char base64code2 = 0; // initialized to 0 to suppress warnings char base64code3; base64code0 = decoding_data[static_cast(input_ptr[i])]; if (base64code0 == nop) // non base64 character return false; if (!(++i < input_length)) // we need at least two input bytes for // first byte output return false; base64code1 = decoding_data[static_cast(input_ptr[i])]; if (base64code1 == nop) // non base64 character return false; output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); if (++i < input_length) { char c = input_ptr[i]; if (c == '=') { // padding , end of input BOOST_ASSERT((base64code1 & 0x0f) == 0); return true; } base64code2 = decoding_data[static_cast(input_ptr[i])]; if (base64code2 == nop) // non base64 character return false; output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f); } if (++i < input_length) { char c = input_ptr[i]; if (c == '=') { // padding , end of input BOOST_ASSERT((base64code2 & 0x03) == 0); return true; } base64code3 = decoding_data[static_cast(input_ptr[i])]; if (base64code3 == nop) // non base64 character return false; output += (((base64code2 << 6) & 0xc0) | base64code3); } } return true; } template bool message_impl::base64_encode( typename message_impl::string_type const &input, typename message_impl::string_type &output) { static const char encoding_data[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned int input_length = input.size(); const char *input_ptr = input.data(); // allocate space for output string output.clear(); output.reserve(((input_length + 2) / 3) * 4); // for each 3-bytes sequence from the input, extract 4 6-bits sequences // and encode using // encoding_data lookup table. // if input do not contains enough chars to complete 3-byte sequence,use // pad char '=' for (unsigned int i = 0; i < input_length; i++) { int base64code0 = 0; int base64code1 = 0; int base64code2 = 0; int base64code3 = 0; base64code0 = (input_ptr[i] >> 2) & 0x3f; // 1-byte 6 bits output += encoding_data[base64code0]; base64code1 = (input_ptr[i] << 4) & 0x3f; // 1-byte 2 bits + if (++i < input_length) { base64code1 |= (input_ptr[i] >> 4) & 0x0f; // 2-byte 4 bits output += encoding_data[base64code1]; base64code2 = (input_ptr[i] << 2) & 0x3f; // 2-byte 4 bits + if (++i < input_length) { base64code2 |= (input_ptr[i] >> 6) & 0x03; // 3-byte 2 bits base64code3 = input_ptr[i] & 0x3f; // 3-byte 6 bits output += encoding_data[base64code2]; output += encoding_data[base64code3]; } else { output += encoding_data[base64code2]; output += '='; } } else { output += encoding_data[base64code1]; output += '='; output += '='; } } return true; } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/parser.ipp000066400000000000000000000711141256751517300253450ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP #include namespace boost { namespace network { namespace http { // member functions for class basic_parser template boost::tribool basic_parser::parse_http_headers( basic_message& http_msg) { // // note that boost::tribool may have one of THREE states: // // false: encountered an error while parsing HTTP headers // true: finished successfully parsing the HTTP headers // indeterminate: parsed bytes, but the HTTP headers are not yet // finished // const char* read_start_ptr = m_read_ptr; m_bytes_last_read = 0; while (m_read_ptr < m_read_end_ptr) { switch (m_headers_parse_state) { case PARSE_METHOD_START: // we have not yet started parsing the HTTP method string if (*m_read_ptr != ' ' && *m_read_ptr != '\r' && *m_read_ptr != '\n') { // ignore leading whitespace if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) return false; m_headers_parse_state = PARSE_METHOD; m_method.erase(); m_method.push_back(*m_read_ptr); } break; case PARSE_METHOD: // we have started parsing the HTTP method string if (*m_read_ptr == ' ') { m_resource.erase(); m_headers_parse_state = PARSE_URI_STEM; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else if (m_method.size() >= ParserTraits::METHOD_MAX) { return false; } else { m_method.push_back(*m_read_ptr); } break; case PARSE_URI_STEM: // we have started parsing the URI stem (or resource name) if (*m_read_ptr == ' ') { m_headers_parse_state = PARSE_HTTP_VERSION_H; } else if (*m_read_ptr == '?') { m_query_string.erase(); m_headers_parse_state = PARSE_URI_QUERY; } else if (is_control(*m_read_ptr)) { return false; } else if (m_resource.size() >= ParserTraits::RESOURCE_MAX) { return false; } else { m_resource.push_back(*m_read_ptr); } break; case PARSE_URI_QUERY: // we have started parsing the URI query string if (*m_read_ptr == ' ') { m_headers_parse_state = PARSE_HTTP_VERSION_H; } else if (is_control(*m_read_ptr)) { return false; } else if (m_query_string.size() >= ParserTraits::QUERY_STRING_MAX) { return false; } else { m_query_string.push_back(*m_read_ptr); } break; case PARSE_HTTP_VERSION_H: // parsing "HTTP" if (*m_read_ptr != 'H') return false; m_headers_parse_state = PARSE_HTTP_VERSION_T_1; break; case PARSE_HTTP_VERSION_T_1: // parsing "HTTP" if (*m_read_ptr != 'T') return false; m_headers_parse_state = PARSE_HTTP_VERSION_T_2; break; case PARSE_HTTP_VERSION_T_2: // parsing "HTTP" if (*m_read_ptr != 'T') return false; m_headers_parse_state = PARSE_HTTP_VERSION_P; break; case PARSE_HTTP_VERSION_P: // parsing "HTTP" if (*m_read_ptr != 'P') return false; m_headers_parse_state = PARSE_HTTP_VERSION_SLASH; break; case PARSE_HTTP_VERSION_SLASH: // parsing slash after "HTTP" if (*m_read_ptr != '/') return false; m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR_START; break; case PARSE_HTTP_VERSION_MAJOR_START: // parsing the first digit of the major version number if (!is_digit(*m_read_ptr)) return false; http_msg.setVersionMajor(*m_read_ptr - '0'); m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR; break; case PARSE_HTTP_VERSION_MAJOR: // parsing the major version number (not first digit) if (*m_read_ptr == '.') { m_headers_parse_state = PARSE_HTTP_VERSION_MINOR_START; } else if (is_digit(*m_read_ptr)) { http_msg.setVersionMajor((http_msg.getVersionMajor() * 10) + (*m_read_ptr - '0')); } else { return false; } break; case PARSE_HTTP_VERSION_MINOR_START: // parsing the first digit of the minor version number if (!is_digit(*m_read_ptr)) return false; http_msg.setVersionMinor(*m_read_ptr - '0'); m_headers_parse_state = PARSE_HTTP_VERSION_MINOR; break; case PARSE_HTTP_VERSION_MINOR: // parsing the major version number (not first digit) if (*m_read_ptr == ' ') { // should only happen for responses if (m_is_request) return false; m_headers_parse_state = PARSE_STATUS_CODE_START; } else if (*m_read_ptr == '\r') { // should only happen for requests if (!m_is_request) return false; m_headers_parse_state = PARSE_EXPECTING_NEWLINE; } else if (*m_read_ptr == '\n') { // should only happen for requests if (!m_is_request) return false; m_headers_parse_state = PARSE_EXPECTING_CR; } else if (is_digit(*m_read_ptr)) { http_msg.setVersionMinor((http_msg.getVersionMinor() * 10) + (*m_read_ptr - '0')); } else { return false; } break; case PARSE_STATUS_CODE_START: // parsing the first digit of the response status code if (!is_digit(*m_read_ptr)) return false; m_status_code = (*m_read_ptr - '0'); m_headers_parse_state = PARSE_STATUS_CODE; break; case PARSE_STATUS_CODE: // parsing the response status code (not first digit) if (*m_read_ptr == ' ') { m_status_message.erase(); m_headers_parse_state = PARSE_STATUS_MESSAGE; } else if (is_digit(*m_read_ptr)) { m_status_code = ((m_status_code * 10) + (*m_read_ptr - '0')); } else { return false; } break; case PARSE_STATUS_MESSAGE: // parsing the response status message if (*m_read_ptr == '\r') { m_headers_parse_state = PARSE_EXPECTING_NEWLINE; } else if (*m_read_ptr == '\n') { m_headers_parse_state = PARSE_EXPECTING_CR; } else if (is_control(*m_read_ptr)) { return false; } else if (m_status_message.size() >= ParserTraits::STATUS_MESSAGE_MAX) { return false; } else { m_status_message.push_back(*m_read_ptr); } break; case PARSE_EXPECTING_NEWLINE: // we received a CR; expecting a newline to follow if (*m_read_ptr == '\n') { m_headers_parse_state = PARSE_HEADER_START; } else if (*m_read_ptr == '\r') { // we received two CR's in a row // assume CR only is (incorrectly) being used for line // termination // therefore, the message is finished ++m_read_ptr; m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return true; } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { m_headers_parse_state = PARSE_HEADER_WHITESPACE; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else { // assume it is the first character for the name of a header m_header_name.erase(); m_header_name.push_back(*m_read_ptr); m_headers_parse_state = PARSE_HEADER_NAME; } break; case PARSE_EXPECTING_CR: // we received a newline without a CR if (*m_read_ptr == '\r') { m_headers_parse_state = PARSE_HEADER_START; } else if (*m_read_ptr == '\n') { // we received two newlines in a row // assume newline only is (incorrectly) being used for line // termination // therefore, the message is finished ++m_read_ptr; m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return true; } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { m_headers_parse_state = PARSE_HEADER_WHITESPACE; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else { // assume it is the first character for the name of a header m_header_name.erase(); m_header_name.push_back(*m_read_ptr); m_headers_parse_state = PARSE_HEADER_NAME; } break; case PARSE_HEADER_WHITESPACE: // parsing whitespace before a header name if (*m_read_ptr == '\r') { m_headers_parse_state = PARSE_EXPECTING_NEWLINE; } else if (*m_read_ptr == '\n') { m_headers_parse_state = PARSE_EXPECTING_CR; } else if (*m_read_ptr != '\t' && *m_read_ptr != ' ') { if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) return false; // assume it is the first character for the name of a header m_header_name.erase(); m_header_name.push_back(*m_read_ptr); m_headers_parse_state = PARSE_HEADER_NAME; } break; case PARSE_HEADER_START: // parsing the start of a new header if (*m_read_ptr == '\r') { m_headers_parse_state = PARSE_EXPECTING_FINAL_NEWLINE; } else if (*m_read_ptr == '\n') { m_headers_parse_state = PARSE_EXPECTING_FINAL_CR; } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { m_headers_parse_state = PARSE_HEADER_WHITESPACE; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else { // first character for the name of a header m_header_name.erase(); m_header_name.push_back(*m_read_ptr); m_headers_parse_state = PARSE_HEADER_NAME; } break; case PARSE_HEADER_NAME: // parsing the name of a header if (*m_read_ptr == ':') { m_header_value.erase(); m_headers_parse_state = PARSE_SPACE_BEFORE_HEADER_VALUE; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else if (m_header_name.size() >= ParserTraits::HEADER_NAME_MAX) { return false; } else { // character (not first) for the name of a header m_header_name.push_back(*m_read_ptr); } break; case PARSE_SPACE_BEFORE_HEADER_VALUE: // parsing space character before a header's value if (*m_read_ptr == ' ') { m_headers_parse_state = PARSE_HEADER_VALUE; } else if (*m_read_ptr == '\r') { http_msg.addHeader(m_header_name, m_header_value); m_headers_parse_state = PARSE_EXPECTING_NEWLINE; } else if (*m_read_ptr == '\n') { http_msg.addHeader(m_header_name, m_header_value); m_headers_parse_state = PARSE_EXPECTING_CR; } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { return false; } else { // assume it is the first character for the value of a header m_header_value.push_back(*m_read_ptr); m_headers_parse_state = PARSE_HEADER_VALUE; } break; case PARSE_HEADER_VALUE: // parsing the value of a header if (*m_read_ptr == '\r') { http_msg.addHeader(m_header_name, m_header_value); m_headers_parse_state = PARSE_EXPECTING_NEWLINE; } else if (*m_read_ptr == '\n') { http_msg.addHeader(m_header_name, m_header_value); m_headers_parse_state = PARSE_EXPECTING_CR; } else if (is_control(*m_read_ptr)) { return false; } else if (m_header_value.size() >= ParserTraits::HEADER_VALUE_MAX) { return false; } else { // character (not first) for the value of a header m_header_value.push_back(*m_read_ptr); } break; case PARSE_EXPECTING_FINAL_NEWLINE: if (*m_read_ptr == '\n') ++m_read_ptr; m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return true; case PARSE_EXPECTING_FINAL_CR: if (*m_read_ptr == '\r') ++m_read_ptr; m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return true; } ++m_read_ptr; } m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return boost::indeterminate; } template boost::tribool basic_parser::parse_chunks( types::chunk_cache_t& chunk_buffers) { // // note that boost::tribool may have one of THREE states: // // false: encountered an error while parsing message // true: finished successfully parsing the message // indeterminate: parsed bytes, but the message is not yet finished // const char* read_start_ptr = m_read_ptr; m_bytes_last_read = 0; while (m_read_ptr < m_read_end_ptr) { switch (m_chunked_content_parse_state) { case PARSE_CHUNK_SIZE_START: // we have not yet started parsing the next chunk size if (is_hex_digit(*m_read_ptr)) { m_chunk_size_str.erase(); m_chunk_size_str.push_back(*m_read_ptr); m_chunked_content_parse_state = PARSE_CHUNK_SIZE; } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09' || *m_read_ptr == '\x0D' || *m_read_ptr == '\x0A') { // Ignore leading whitespace. Technically, the standard // probably doesn't allow white space here, // but we'll be flexible, since there's no ambiguity. break; } else { return false; } break; case PARSE_CHUNK_SIZE: if (is_hex_digit(*m_read_ptr)) { m_chunk_size_str.push_back(*m_read_ptr); } else if (*m_read_ptr == '\x0D') { m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { // Ignore trailing tabs or spaces. Technically, the standard // probably doesn't allow this, // but we'll be flexible, since there's no ambiguity. m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE; } else { return false; } break; case PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE: if (*m_read_ptr == '\x0D') { m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { // Ignore trailing tabs or spaces. Technically, the standard // probably doesn't allow this, // but we'll be flexible, since there's no ambiguity. break; } else { return false; } break; case PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE: // We received a CR; expecting LF to follow. We can't be flexible // here because // if we see anything other than LF, we can't be certain where the // chunk starts. if (*m_read_ptr == '\x0A') { m_bytes_read_in_current_chunk = 0; m_size_of_current_chunk = strtol(m_chunk_size_str.c_str(), 0, 16); if (m_size_of_current_chunk == 0) { m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK; } else { m_current_chunk.clear(); m_chunked_content_parse_state = PARSE_CHUNK; } } else { return false; } break; case PARSE_CHUNK: if (m_bytes_read_in_current_chunk < m_size_of_current_chunk) { m_current_chunk.push_back(*m_read_ptr); m_bytes_read_in_current_chunk++; } if (m_bytes_read_in_current_chunk == m_size_of_current_chunk) { chunk_buffers.push_back(m_current_chunk); m_current_chunk.clear(); m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK; } break; case PARSE_EXPECTING_CR_AFTER_CHUNK: // we've read exactly m_size_of_current_chunk bytes since starting // the current chunk if (*m_read_ptr == '\x0D') { m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK; } else { return false; } break; case PARSE_EXPECTING_LF_AFTER_CHUNK: // we received a CR; expecting LF to follow if (*m_read_ptr == '\x0A') { m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; } else { return false; } break; case PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK: // we've read the final chunk; expecting final CRLF if (*m_read_ptr == '\x0D') { m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK; } else { return false; } break; case PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK: // we received the final CR; expecting LF to follow if (*m_read_ptr == '\x0A') { ++m_read_ptr; m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return true; } else { return false; } } ++m_read_ptr; } m_bytes_last_read = (m_read_ptr - read_start_ptr); m_bytes_total_read += m_bytes_last_read; return boost::indeterminate; } template std::size_t basic_parser::consume_content( basic_message& http_msg) { // get the payload content length from the HTTP headers http_msg.updateContentLengthUsingHeader(); // read the post content std::size_t content_bytes_to_read = http_msg.getContentLength(); char* post_buffer = http_msg.createContentBuffer(); if (m_read_ptr < m_read_end_ptr) { // there are extra bytes left from the last read operation // copy them into the beginning of the content buffer const std::size_t bytes_left_in_read_buffer = bytes_available(); if (bytes_left_in_read_buffer >= http_msg.getContentLength()) { // the last read operation included all of the payload content memcpy(post_buffer, m_read_ptr, http_msg.getContentLength()); content_bytes_to_read = 0; m_read_ptr += http_msg.getContentLength(); } else { // only some of the post content has been read so far memcpy(post_buffer, m_read_ptr, bytes_left_in_read_buffer); content_bytes_to_read -= bytes_left_in_read_buffer; m_read_ptr = m_read_end_ptr; } } m_bytes_last_read = (http_msg.getContentLength() - content_bytes_to_read); m_bytes_total_read += m_bytes_last_read; return m_bytes_last_read; } template std::size_t basic_parser::consume_content_as_next_chunk( types::chunk_cache_t& chunk_buffers) { if (bytes_available() == 0) { m_bytes_last_read = 0; } else { std::vector next_chunk; while (m_read_ptr < m_read_end_ptr) { next_chunk.push_back(*m_read_ptr); ++m_read_ptr; } chunk_buffers.push_back(next_chunk); m_bytes_last_read = next_chunk.size(); m_bytes_total_read += m_bytes_last_read; } return m_bytes_last_read; } template void basic_parser::finish(basic_request& http_request) { http_request.setIsValid(true); http_request.setMethod(m_method); http_request.setResource(m_resource); http_request.setQueryString(m_query_string); // parse query pairs from the URI query string if (!m_query_string.empty()) { if (!parseURLEncoded(http_request.getQueryParams(), m_query_string.c_str(), m_query_string.size())) } // parse query pairs from post content (x-www-form-urlencoded) if (http_request.getHeader(types::HEADER_CONTENT_TYPE) == types::CONTENT_TYPE_URLENCODED) { if (!parseURLEncoded(http_request.getQueryParams(), http_request.getContent(), http_request.getContentLength())) } // parse "Cookie" headers std::pair cookie_pair = http_request.getHeaders().equal_range(types::HEADER_COOKIE); for (types::headers::const_iterator cookie_iterator = cookie_pair.first; cookie_iterator != http_request.getHeaders().end() && cookie_iterator != cookie_pair.second; ++cookie_iterator) { if (!parseCookieHeader(http_request.getCookieParams(), cookie_iterator->second)) } } template void basic_parser::finish(basic_response& http_response) { http_response.setIsValid(true); http_response.setStatusCode(m_status_code); http_response.setStatusMessage(m_status_message); } template inline void basic_parser::reset(void) { m_headers_parse_state = (m_is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H); m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; m_status_code = 0; m_status_message.erase(); m_method.erase(); m_resource.erase(); m_query_string.erase(); m_current_chunk.clear(); m_bytes_last_read = m_bytes_total_read = 0; } template static bool basic_parser::parse_url_encoded( types::query_params& params, const char* ptr, const std::size_t len) { // used to track whether we are parsing the name or value enum query_parse_state_t { QUERY_PARSE_NAME, QUERY_PARSE_VALUE } parse_state = QUERY_PARSE_NAME; // misc other variables used for parsing const char* const end = ptr + len; string_type query_name; string_type query_value; // iterate through each encoded character while (ptr < end) { switch (parse_state) { case QUERY_PARSE_NAME: // parsing query name if (*ptr == '=') { // end of name found if (query_name.empty()) return false; parse_state = QUERY_PARSE_VALUE; } else if (*ptr == '&') { // value is empty (OK) if (query_name.empty()) return false; params.insert(std::make_pair(query_name, query_value)); query_name.erase(); } else if (is_control(*ptr) || query_name.size() >= ParserTraits::QUERY_NAME_MAX) { // control character detected, or max sized exceeded return false; } else { // character is part of the name query_name.push_back(*ptr); } break; case QUERY_PARSE_VALUE: // parsing query value if (*ptr == '&') { // end of value found (OK if empty) params.insert(std::make_pair(query_name, query_value)); query_name.erase(); query_value.erase(); parse_state = QUERY_PARSE_NAME; } else if (is_control(*ptr) || query_value.size() >= ParserTraits::QUERY_VALUE_MAX) { // control character detected, or max sized exceeded return false; } else { // character is part of the value query_value.push_back(*ptr); } break; } ++ptr; } // handle last pair in string if (!query_name.empty()) params.insert(std::make_pair(query_name, query_value)); return true; } template static bool basic_parser::parse_cookie_header( types::cookie_params& params, const string_type& cookie_header) { // BASED ON RFC 2109 // // The current implementation ignores cookie attributes which begin with // '$' // (i.e. $Path=/, $Domain=, etc.) // used to track what we are parsing enum cookie_parse_state_t { COOKIE_PARSE_NAME, COOKIE_PARSE_VALUE, COOKIE_PARSE_IGNORE } parse_state = COOKIE_PARSE_NAME; // misc other variables used for parsing string_type cookie_name; string_type cookie_value; char value_quote_character = '\0'; // iterate through each character for (string_type::const_iterator string_iterator = cookie_header.begin(); string_iterator != cookie_header.end(); ++string_iterator) { switch (parse_state) { case COOKIE_PARSE_NAME: // parsing cookie name if (*string_iterator == '=') { // end of name found if (cookie_name.empty()) return false; value_quote_character = '\0'; parse_state = COOKIE_PARSE_VALUE; } else if (*string_iterator == ';' || *string_iterator == ',') { // ignore empty cookie names since this may occur naturally // when quoted values are encountered if (!cookie_name.empty()) { // value is empty (OK) if (cookie_name[0] != '$') params.insert(std::make_pair(cookie_name, cookie_value)); cookie_name.erase(); } } else if (*string_iterator != ' ') { // ignore whitespace // check if control character detected, or max sized exceeded if (is_control(*string_iterator) || cookie_name.size() >= ParserTraits::COOKIE_NAME_MAX) return false; // character is part of the name // cookie names are case insensitive -> convert to lowercase cookie_name.push_back(tolower(*string_iterator)); } break; case COOKIE_PARSE_VALUE: // parsing cookie value if (value_quote_character == '\0') { // value is not (yet) quoted if (*string_iterator == ';' || *string_iterator == ',') { // end of value found (OK if empty) if (cookie_name[0] != '$') params.insert(std::make_pair(cookie_name, cookie_value)); cookie_name.erase(); cookie_value.erase(); parse_state = COOKIE_PARSE_NAME; } else if (*string_iterator == '\'' || *string_iterator == '"') { if (cookie_value.empty()) { // begin quoted value value_quote_character = *string_iterator; } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { // max size exceeded return false; } else { // assume character is part of the (unquoted) value cookie_value.push_back(*string_iterator); } } else if (*string_iterator != ' ') { // ignore unquoted whitespace // check if control character detected, or max sized exceeded if (is_control(*string_iterator) || cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) return false; // character is part of the (unquoted) value cookie_value.push_back(*string_iterator); } } else { // value is quoted if (*string_iterator == value_quote_character) { // end of value found (OK if empty) if (cookie_name[0] != '$') params.insert(std::make_pair(cookie_name, cookie_value)); cookie_name.erase(); cookie_value.erase(); parse_state = COOKIE_PARSE_IGNORE; } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { // max size exceeded return false; } else { // character is part of the (quoted) value cookie_value.push_back(*string_iterator); } } break; case COOKIE_PARSE_IGNORE: // ignore everything until we reach a comma "," or semicolon ";" if (*string_iterator == ';' || *string_iterator == ',') parse_state = COOKIE_PARSE_NAME; break; } } // handle last cookie in string if (!cookie_name.empty() && cookie_name[0] != '$') params.insert(std::make_pair(cookie_name, cookie_value)); return true; } }; // namespace http }; // namespace network }; // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/request.hpp000066400000000000000000000165211256751517300255410ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007,2009,2010. // Copyright Michael Dickey 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ #define __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { /** Specialize the traits for the http_server tag. */ template <> struct headers_container< http::tags::http_server> : vector:: apply::type> {}; template <> struct headers_container< http::tags:: http_async_server> : vector:: apply::type> {}; namespace http { /** request.hpp * * This file implements the basic request object required * by the HTTP client implementation. The basic_request * object encapsulates a URI which is parsed at runtime. */ template struct basic_request : public basic_message { mutable boost::network::uri::uri uri_; boost::uint16_t source_port_; typedef basic_message base_type; public: typedef typename sync_only::type tag; typedef typename string::type string_type; typedef boost::uint16_t port_type; explicit basic_request(string_type const& uri_) : uri_(uri_), source_port_(0) {} explicit basic_request(boost::network::uri::uri const& uri_) : uri_(uri_), source_port_(0) {} void uri(string_type const& new_uri) { uri_ = new_uri; } void uri(boost::network::uri::uri const& new_uri) { uri_ = new_uri; } basic_request() : base_type(), source_port_(0) {} basic_request(basic_request const& other) : base_type(other), uri_(other.uri_), source_port_(other.source_port_) {} basic_request& operator=(basic_request rhs) { rhs.swap(*this); return *this; } void swap(basic_request& other) { base_type& base_ref(other); basic_request& this_ref(*this); base_ref.swap(this_ref); boost::swap(other.uri_, this->uri_); boost::swap(other.source_port_, this->source_port_); } string_type const host() const { return uri_.host(); } port_type port() const { boost::optional port = uri::port_us(uri_); if (!port) { typedef constants consts; return boost::iequals(uri_.scheme(), string_type(consts::https())) ? 443 : 80; } return *port; } string_type const path() const { return uri_.path(); } string_type const query() const { return uri_.query(); } string_type const anchor() const { return uri_.fragment(); } string_type const protocol() const { return uri_.scheme(); } void uri(string_type const& new_uri) const { uri_ = new_uri; } boost::network::uri::uri const& uri() const { return uri_; } void source_port(const boost::uint16_t port) { source_port_ = port; } boost::uint16_t source_port() const { return source_port_; } }; /** This is the implementation of a POD request type * that is specificially used by the HTTP server * implementation. This fully specializes the * basic_request template above to be * primarily and be solely a POD for performance * reasons. * * Reality check: This is not a POD because it contains a non-POD * member, the headers vector. :( */ template struct not_quite_pod_request_base { typedef Tag tag; typedef typename string::type string_type; typedef typename request_header::type header_type; typedef typename vector::template apply::type vector_type; typedef vector_type headers_container_type; typedef boost::uint16_t port_type; mutable string_type source; mutable port_type source_port; mutable string_type method; mutable string_type destination; mutable boost::uint8_t http_version_major; mutable boost::uint8_t http_version_minor; mutable vector_type headers; mutable string_type body; void swap(not_quite_pod_request_base& r) const { using std::swap; swap(method, r.method); swap(source, r.source); swap(source_port, r.source_port); swap(destination, r.destination); swap(http_version_major, r.http_version_major); swap(http_version_minor, r.http_version_minor); swap(headers, r.headers); swap(body, r.body); } }; template <> struct basic_request : not_quite_pod_request_base< tags::http_async_server> {}; template <> struct basic_request : not_quite_pod_request_base< tags::http_server> {}; template struct ServerRequest; BOOST_CONCEPT_ASSERT((ServerRequest >)); BOOST_CONCEPT_ASSERT((ServerRequest >)); template inline void swap(basic_request& lhs, basic_request& rhs) { lhs.swap(rhs); } } // namespace http namespace http { namespace impl { template <> struct request_headers_wrapper { basic_request const& request_; request_headers_wrapper(basic_request const& request_) : request_(request_) {} typedef headers_container::type headers_container_type; operator headers_container_type() { return request_.headers; } }; template <> struct body_wrapper > { typedef string::type string_type; basic_request const& request_; body_wrapper(basic_request const& request_) : request_(request_) {} operator string_type() { return request_.body; } }; template <> struct request_headers_wrapper { basic_request const& request_; request_headers_wrapper( basic_request const& request_) : request_(request_) {} typedef headers_container::type headers_container_type; operator headers_container_type() { return request_.headers; } }; template <> struct body_wrapper > { typedef string::type string_type; basic_request const& request_; body_wrapper(basic_request const& request_) : request_(request_) {} operator string_type() { return request_.body; } }; } // namespace impl } // namespace http } // namespace network } // namespace boost #endif // __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/request_parser.ipp000066400000000000000000000155761256751517300271270ustar00rootroot00000000000000// // request_parser.ipp // ~~~~~~~~~~~~~~~~~~ // // Implementation file for the header-only version of the request_parser. // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) // Copyright (c) 2009 Tarroo, Inc. // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP #define BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP #include namespace boost { namespace network { namespace http { template boost::tribool basic_request_parser::consume(basic_request& req, char input) { switch (state_) { case method_start: if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { return false; } else { state_ = method; req.method.push_back(input); return boost::indeterminate; } case method: if (input == ' ') { state_ = uri; return boost::indeterminate; } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { return false; } else { req.method.push_back(input); return boost::indeterminate; } case uri_start: if (is_ctl(input)) { return false; } else { state_ = uri; req.destination.push_back(input); return boost::indeterminate; } case uri: if (input == ' ') { state_ = http_version_h; return boost::indeterminate; } else if (is_ctl(input)) { return false; } else { req.destination.push_back(input); return boost::indeterminate; } case http_version_h: if (input == 'H') { state_ = http_version_t_1; return boost::indeterminate; } else { return false; } case http_version_t_1: if (input == 'T') { state_ = http_version_t_2; return boost::indeterminate; } else { return false; } case http_version_t_2: if (input == 'T') { state_ = http_version_p; return boost::indeterminate; } else { return false; } case http_version_p: if (input == 'P') { state_ = http_version_slash; return boost::indeterminate; } else { return false; } case http_version_slash: if (input == '/') { req.http_version_major = 0; req.http_version_minor = 0; state_ = http_version_major_start; return boost::indeterminate; } else { return false; } case http_version_major_start: if (is_digit(input)) { req.http_version_major = req.http_version_major * 10 + input - '0'; state_ = http_version_major; return boost::indeterminate; } else { return false; } case http_version_major: if (input == '.') { state_ = http_version_minor_start; return boost::indeterminate; } else if (is_digit(input)) { req.http_version_major = req.http_version_major * 10 + input - '0'; return boost::indeterminate; } else { return false; } case http_version_minor_start: if (is_digit(input)) { req.http_version_minor = req.http_version_minor * 10 + input - '0'; state_ = http_version_minor; return boost::indeterminate; } else { return false; } case http_version_minor: if (input == '\r') { state_ = expecting_newline_1; return boost::indeterminate; } else if (is_digit(input)) { req.http_version_minor = req.http_version_minor * 10 + input - '0'; return boost::indeterminate; } else { return false; } case expecting_newline_1: if (input == '\n') { state_ = header_line_start; return boost::indeterminate; } else { return false; } case header_line_start: if (input == '\r') { state_ = expecting_newline_3; return boost::indeterminate; } else if (!req.headers.empty() && (input == ' ' || input == '\t')) { state_ = header_lws; return boost::indeterminate; } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { return false; } else { req.headers.push_back(typename request_header::type()); req.headers.back().name.push_back(input); state_ = header_name; return boost::indeterminate; } case header_lws: if (input == '\r') { state_ = expecting_newline_2; return boost::indeterminate; } else if (input == ' ' || input == '\t') { return boost::indeterminate; } else if (is_ctl(input)) { return false; } else { state_ = header_value; req.headers.back().value.push_back(input); return boost::indeterminate; } case header_name: if (input == ':') { state_ = space_before_header_value; return boost::indeterminate; } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { return false; } else { req.headers.back().name.push_back(input); return boost::indeterminate; } case space_before_header_value: if (input == ' ') { state_ = header_value; return boost::indeterminate; } else { return false; } case header_value: if (input == '\r') { state_ = expecting_newline_2; return boost::indeterminate; } else if (is_ctl(input)) { return false; } else { req.headers.back().value.push_back(input); return boost::indeterminate; } case expecting_newline_2: if (input == '\n') { state_ = header_line_start; return boost::indeterminate; } else { return false; } case expecting_newline_3: return (input == '\n'); default: return false; } } template bool basic_request_parser::is_char(int c) { return c >= 0 && c <= 127; } template bool basic_request_parser::is_ctl(int c) { return (c >= 0 && c <= 31) || (c == 127); } template bool basic_request_parser::is_tspecial(int c) { switch (c) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case ':': case '\\': case '"': case '/': case '[': case ']': case '?': case '=': case '{': case '}': case ' ': case '\t': return true; default: return false; } } template bool basic_request_parser::is_digit(int c) { return c >= '0' && c <= '9'; } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/impl/response.ipp000066400000000000000000000507471256751517300257200ustar00rootroot00000000000000// // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) // Copyright (c) 2009 Tarroo, Inc. // Copyright (c) 2014 Jussi Lyytinen (jussi@lyytinen.org) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Note: This implementation has significantly changed from the original example // from a plain header file into a header-only implementation using C++ // templates // to reduce the dependence on building an external library. // #ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP #include #include #include #include #include #include namespace boost { namespace network { namespace http { /// A reply to be sent to a client. template <> struct basic_response { typedef tags::http_server tag; typedef response_header::type header_type; /*! The status of the reply. Represent all the status codes of HTTP v1.1 * from http://tools.ietf.org/html/rfc2616#page-39 and * http://tools.ietf.org/html/rfc6585 */ enum status_type { continue_http = 100, switching_protocols = 101, ok = 200, created = 201, accepted = 202, non_authoritative_information = 203, no_content = 204, reset_content = 205, partial_content = 206, multiple_choices = 300, moved_permanently = 301, moved_temporarily = 302, ///< \deprecated Not HTTP standard found = 302, see_other = 303, not_modified = 304, use_proxy = 305, temporary_redirect = 307, bad_request = 400, unauthorized = 401, payment_required = 402, forbidden = 403, not_found = 404, not_supported = 405, ///< \deprecated Not HTTP standard method_not_allowed = 405, not_acceptable = 406, proxy_authentication_required = 407, request_timeout = 408, conflict = 409, gone = 410, length_required = 411, precondition_failed = 412, request_entity_too_large = 413, request_uri_too_large = 414, unsupported_media_type = 415, unsatisfiable_range = 416, ///< \deprecated Not HTTP standard requested_range_not_satisfiable = 416, expectation_failed = 417, precondition_required = 428, too_many_requests = 429, request_header_fields_too_large = 431, internal_server_error = 500, not_implemented = 501, bad_gateway = 502, service_unavailable = 503, gateway_timeout = 504, http_version_not_supported = 505, space_unavailable = 507, network_authentication_required = 511 } status; /// The headers to be included in the reply. typedef vector::apply::type headers_vector; headers_vector headers; /// The content to be sent in the reply. typedef string::type string_type; string_type content; /// Convert the reply into a vector of buffers. The buffers do not own /// the /// underlying memory blocks, therefore the reply object must remain /// valid and /// not be changed until the write operation has completed. std::vector to_buffers() { using boost::asio::const_buffer; using boost::asio::buffer; static const char name_value_separator[] = {':', ' '}; static const char crlf[] = {'\r', '\n'}; std::vector buffers; buffers.push_back(to_buffer(status)); for (std::size_t i = 0; i < headers.size(); ++i) { header_type &h = headers[i]; buffers.push_back(buffer(h.name)); buffers.push_back(buffer(name_value_separator)); buffers.push_back(buffer(h.value)); buffers.push_back(buffer(crlf)); } buffers.push_back(buffer(crlf)); buffers.push_back(buffer(content)); return buffers; } /// Get a stock reply. static basic_response stock_reply(status_type status) { return stock_reply(status, to_string(status)); } /// Get a stock reply with custom plain text data. static basic_response stock_reply(status_type status, string_type content) { using boost::lexical_cast; basic_response rep; rep.status = status; rep.content = content; rep.headers.resize(2); rep.headers[0].name = "Content-Length"; rep.headers[0].value = lexical_cast(rep.content.size()); rep.headers[1].name = "Content-Type"; rep.headers[1].value = "text/html"; return rep; } /// Swap response objects void swap(basic_response &r) { using std::swap; swap(headers, r.headers); swap(content, r.content); } private: static string_type to_string(status_type status) { switch (status) { // 2xx Success case basic_response::ok: return ""; case basic_response::created: return "" "Created" "

201 Created

" ""; case basic_response::accepted: return "" "Accepted" "

202 Accepted

" ""; case basic_response::non_authoritative_information: return "" "Non-Authoritative Information" "

203 Non-Authoritative Information

" ""; case basic_response::no_content: return "" "No Content" "

204 Content

" ""; case basic_response::reset_content: return "" "Reset Content" "

205 Reset Content

" ""; case basic_response::partial_content: return "" "Partial Content" "

206 Partial Content

" ""; // 3xx Redirection case basic_response::multiple_choices: return "" "Multiple Choices" "

300 Multiple Choices

" ""; case basic_response::moved_permanently: return "" "Moved Permanently" "

301 Moved Permanently

" ""; case basic_response::moved_temporarily: return "" "Moved Temporarily" "

302 Moved Temporarily

" ""; case basic_response::see_other: return "" "See Other" "

303 See Other

" ""; case basic_response::not_modified: return "" "Not Modified" "

304 Not Modified

" ""; case basic_response::use_proxy: return "" "Use Proxy" "

305 Use Proxy

" ""; case basic_response::temporary_redirect: return "" "Temporary Redirect" "

307 Temporary Redirect

" ""; // 4xx Client Error case basic_response::bad_request: return "" "Bad Request" "

400 Bad Request

" ""; case basic_response::unauthorized: return "" "Unauthorized" "

401 Unauthorized

" ""; case basic_response::forbidden: return "" "Forbidden" "

403 Forbidden

" ""; case basic_response::not_found: return "" "Not Found" "

404 Not Found

" ""; case basic_response::not_supported: return "" "Method Not Supported" "

405 Method Not Supported

" ""; case basic_response::not_acceptable: return "" "Not Acceptable\r\n" "

406 Not Acceptable

" ""; case basic_response::proxy_authentication_required: return "" "Proxy Authentication Required" "

407 Proxy Authentication Required

" ""; case basic_response::request_timeout: return "" "Request Timeout" "

408 Request Timeout

" ""; case basic_response::conflict: return "" "Conflict" "

409 Conflict

" ""; case basic_response::gone: return "" "Gone" "

410 Gone

" ""; case basic_response::length_required: return "" "Length Required" "

411 Length Required

" ""; case basic_response::precondition_failed: return "" "Precondition Failed" "

412 Precondition Failed

" ""; case basic_response::request_entity_too_large: return "" "Request Entity Too Large" "

413 Request Entity Too Large

" ""; case basic_response::request_uri_too_large: return "" "Request-URI Too Large" "

414 Request-URI Too Large

" ""; case basic_response::unsupported_media_type: return "" "Unsupported Media Type" "

415 Unsupported Media Type

" ""; case basic_response::unsatisfiable_range: return "" "Unsatisfiable Range" "

416 Requested Range Not " "Satisfiable

" ""; case basic_response::expectation_failed: return "" "Expectation Failed" "

417 Expectation Failed

" ""; case basic_response::precondition_required: return "" "Precondition Required" "

428 Precondition Required

" ""; case basic_response::too_many_requests: return "" "Too Many Requests" "

429 Too Many Requests

" ""; case basic_response::request_header_fields_too_large: return "" "Request Header Fields Too Large" "

431 Request Header Fields Too Large

" ""; // 5xx Server Error case basic_response::internal_server_error: return "" "Internal Server Error" "

500 Internal Server Error

" ""; case basic_response::not_implemented: return "" "Not Implemented" "

501 Not Implemented

" ""; case basic_response::bad_gateway: return "" "Bad Gateway" "

502 Bad Gateway

" ""; case basic_response::service_unavailable: return "" "Service Unavailable" "

503 Service Unavailable

" ""; case basic_response::gateway_timeout: return "" "Gateway Timeout" "

504 Gateway Timeout

" ""; case basic_response::http_version_not_supported: return "" "HTTP Version Not Supported" "

505 HTTP Version Not Supported

" ""; case basic_response::space_unavailable: return "" "Space Unavailable" "

507 Insufficient Space to Store " "Resource

" ""; default: return "" "Internal Server Error" "

500 Internal Server Error

" ""; } } boost::asio::const_buffer trim_null(boost::asio::const_buffer buffer) { std::size_t size = boost::asio::buffer_size(buffer); return boost::asio::buffer(buffer, size - 1); } boost::asio::const_buffer to_buffer(status_type status) { using boost::asio::buffer; switch (status) { // 2xx Success case basic_response::ok: return trim_null(buffer("HTTP/1.1 200 OK\r\n")); case basic_response::created: return trim_null(buffer("HTTP/1.1 201 Created\r\n")); case basic_response::accepted: return trim_null(buffer("HTTP/1.1 202 Accepted\r\n")); case basic_response::non_authoritative_information: return trim_null(buffer("HTTP/1.1 203 Non-Authoritative Information\r\n")); case basic_response::no_content: return trim_null(buffer("HTTP/1.1 204 No Content\r\n")); case basic_response::reset_content: return trim_null(buffer("HTTP/1.1 205 Reset Content\r\n")); case basic_response::partial_content: return trim_null(buffer("HTTP/1.1 206 Partial Content\r\n")); // 3xx Redirection case basic_response::multiple_choices: return trim_null(buffer("HTTP/1.1 300 Multiple Choices\r\n")); case basic_response::moved_permanently: return trim_null(buffer("HTTP/1.1 301 Moved Permanently\r\n")); case basic_response::moved_temporarily: return trim_null(buffer("HTTP/1.1 302 Moved Temporarily\r\n")); case basic_response::see_other: return trim_null(buffer("HTTP/1.1 303 See Other\r\n")); case basic_response::not_modified: return trim_null(buffer("HTTP/1.1 304 Not Modified\r\n")); case basic_response::use_proxy: return trim_null(buffer("HTTP/1.1 305 Use Proxy\r\n")); case basic_response::temporary_redirect: return trim_null(buffer("HTTP/1.1 307 Temporary Redirect\r\n")); // 4xx Client Error case basic_response::bad_request: return trim_null(buffer("HTTP/1.1 400 Bad Request\r\n")); case basic_response::unauthorized: return trim_null(buffer("HTTP/1.1 401 Unauthorized\r\n")); case basic_response::forbidden: return trim_null(buffer("HTTP/1.1 403 Forbidden\r\n")); case basic_response::not_found: return trim_null(buffer("HTTP/1.1 404 Not Found\r\n")); case basic_response::not_supported: return trim_null(buffer("HTTP/1.1 405 Method Not Supported\r\n")); case basic_response::not_acceptable: return trim_null(buffer("HTTP/1.1 406 Method Not Acceptable\r\n")); case basic_response::proxy_authentication_required: return trim_null(buffer("HTTP/1.1 407 Proxy Authentication Required\r\n")); case basic_response::request_timeout: return trim_null(buffer("HTTP/1.1 408 Request Timeout\r\n")); case basic_response::conflict: return trim_null(buffer("HTTP/1.1 409 Conflict\r\n")); case basic_response::gone: return trim_null(buffer("HTTP/1.1 410 Gone\r\n")); case basic_response::length_required: return trim_null(buffer("HTTP/1.1 411 Length Required\r\n")); case basic_response::precondition_failed: return trim_null(buffer("HTTP/1.1 412 Precondition Failed\r\n")); case basic_response::request_entity_too_large: return trim_null(buffer("HTTP/1.1 413 Request Entity Too Large\r\n")); case basic_response::request_uri_too_large: return trim_null(buffer("HTTP/1.1 414 Request-URI Too Large\r\n")); case basic_response::unsupported_media_type: return trim_null(buffer("HTTP/1.1 415 Unsupported Media Type\r\n")); case basic_response::unsatisfiable_range: return trim_null(buffer("HTTP/1.1 416 Requested Range Not Satisfiable\r\n")); case basic_response::precondition_required: return trim_null(buffer("HTTP/1.1 428 Precondition Required\r\n")); case basic_response::too_many_requests: return trim_null(buffer("HTTP/1.1 429 Too Many Requests\r\n")); case basic_response::request_header_fields_too_large: return trim_null(buffer("HTTP/1.1 431 Request Header Fields Too Large\r\n")); // 5xx Server Error case basic_response::internal_server_error: return trim_null(buffer("HTTP/1.1 500 Internal Server Error\r\n")); case basic_response::not_implemented: return trim_null(buffer("HTTP/1.1 501 Not Implemented\r\n")); case basic_response::bad_gateway: return trim_null(buffer("HTTP/1.1 502 Bad Gateway\r\n")); case basic_response::service_unavailable: return trim_null(buffer("HTTP/1.1 503 Service Unavailable\r\n")); case basic_response::gateway_timeout: return trim_null(buffer("HTTP/1.1 504 Gateway Timeout\r\n")); case basic_response::http_version_not_supported: return trim_null(buffer("HTTP/1.1 505 HTTP Version Not Supported\r\n")); case basic_response::space_unavailable: return trim_null(buffer("HTTP/1.1 507 Insufficient Space to Store Resource\r\n")); default: return trim_null(buffer("HTTP/1.1 500 Internal Server Error\r\n")); } } }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/message.hpp000066400000000000000000000103061256751517300245270ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Some changes Copyright (c) Dean Michael Berris 2008 #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { /// base class for HTTP messages (requests and responses) template struct message_impl : public basic_message { typedef typename string::type string_type; /// escapes URL-encoded strings (a%20value+with%20spaces) static string_type const url_decode(string_type const &str); /// encodes strings so that they are safe for URLs (with%20spaces) static string_type const url_encode(string_type const &str); /// builds an HTTP query string from a collection of query parameters static string_type const make_query_string( typename query_container::type const &query_params); /** * creates a "Set-Cookie" header * * @param name the name of the cookie * @param value the value of the cookie * @param path the path of the cookie * @param has_max_age true if the max_age value should be set * @param max_age the life of the cookie, in seconds (0 = discard) * * @return the new "Set-Cookie" header */ static string_type const make_set_cookie_header( string_type const &name, string_type const &value, string_type const &path, bool const has_max_age = false, unsigned long const max_age = 0); /** decodes base64-encoded strings * * @param input base64 encoded string * @param output decoded string ( may include non-text chars) * @return true if successful, false if input string contains non-base64 *symbols */ static bool base64_decode(string_type const &input, string_type &output); /** encodes strings using base64 * * @param input arbitrary string ( may include non-text chars) * @param output base64 encoded string * @return true if successful */ static bool base64_encode(string_type const &input, string_type &output); protected: mutable string_type version_; mutable boost::uint16_t status_; mutable string_type status_message_; private: typedef basic_message base_type; public: message_impl() : base_type(), version_(), status_(0u), status_message_() {} message_impl(message_impl const &other) : base_type(other), version_(other.version_), status_(other.status_), status_message_(other.status_message_) {} void version(string_type const &version) const { version_ = version; } string_type const version() const { return version_; } void status(boost::uint16_t status) const { status_ = status; } boost::uint16_t status() const { return status_; } void status_message(string_type const &status_message) const { status_message_ = status_message; } string_type const status_message() const { return status_message_; } message_impl &operator=(message_impl rhs) { rhs.swap(*this); return *this; } void swap(message_impl &other) { base_type &base_ref(other), &this_ref(*this); std::swap(this_ref, base_ref); std::swap(status_, other.status_); std::swap(status_message_, other.status_message_); std::swap(version_, other.version_); } }; template inline void swap(message_impl &lhs, message_impl &rhs) { lhs.swap(rhs); } typedef message_impl message; } // namespace http } // namespace network } // namespace boost // import implementation file #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/message/000077500000000000000000000000001256751517300240165ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/async_message.hpp000066400000000000000000000106671256751517300273620ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include // FIXME move this out to a trait #include #include #include namespace boost { namespace network { namespace http { namespace impl { template struct ready_wrapper; } /* impl */ template struct async_message { typedef typename string::type string_type; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::value_type header_type; async_message() : status_message_(), version_(), source_(), destination_(), status_(), headers_(), body_() {} async_message(async_message const& other) : status_message_(other.status_message_), version_(other.version_), source_(other.source_), destination_(other.destination_), status_(other.status_), headers_(other.headers_), body_(other.body_) {} string_type const status_message() const { return status_message_.get(); } void status_message(boost::shared_future const& future) const { status_message_ = future; } string_type const version() const { return version_.get(); } void version(boost::shared_future const& future) const { version_ = future; } boost::uint16_t status() const { return status_.get(); } void status(boost::shared_future const& future) const { status_ = future; } string_type const source() const { return source_.get(); } void source(boost::shared_future const& future) const { source_ = future; } string_type const destination() const { return destination_.get(); } void destination(boost::shared_future const& future) const { destination_ = future; } headers_container_type const& headers() const { if (retrieved_headers_) return *retrieved_headers_; headers_container_type raw_headers = headers_.get(); raw_headers.insert(added_headers.begin(), added_headers.end()); BOOST_FOREACH(string_type const & key, removed_headers) { raw_headers.erase(key); } retrieved_headers_ = raw_headers; return *retrieved_headers_; } void headers(boost::shared_future const& future) const { headers_ = future; } void add_header(typename headers_container_type::value_type const& pair_) const { added_headers.insert(added_headers.end(), pair_); } void remove_header(typename headers_container_type::key_type const& key_) const { removed_headers.insert(key_); } string_type const body() const { return body_.get(); } void body(boost::shared_future const& future) const { body_ = future; } void swap(async_message& other) { std::swap(status_message_, other.status_message_); std::swap(status_, other.status_); std::swap(version_, other.version_); std::swap(source_, other.source_); std::swap(destination_, other.destination_); std::swap(headers_, other.headers_); std::swap(body_, other.body_); } async_message& operator=(async_message other) { other.swap(*this); return *this; } private: mutable boost::shared_future status_message_, version_, source_, destination_; mutable boost::shared_future status_; mutable boost::shared_future headers_; mutable headers_container_type added_headers; mutable std::set removed_headers; mutable boost::shared_future body_; mutable boost::optional retrieved_headers_; friend struct boost::network::http::impl::ready_wrapper; }; template inline void swap(async_message& lhs, async_message& rhs) { lhs.swap(rhs); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/000077500000000000000000000000001256751517300261575ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/major_version.hpp000066400000000000000000000022231256751517300315440ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; struct major_version_directive { boost::uint8_t major_version; explicit major_version_directive(boost::uint8_t major_version) : major_version(major_version) {} template void operator()(basic_request& request) const { request.http_version_major = major_version; } }; inline major_version_directive major_version(boost::uint8_t major_version_) { return major_version_directive(major_version_); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/method.hpp000066400000000000000000000012411256751517300301460ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { BOOST_NETWORK_STRING_DIRECTIVE(method, method_, message.method(method_), message.method = method_); } /* http */ } /* network */ } /* booet */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/minor_version.hpp000066400000000000000000000022231256751517300315600ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; struct minor_version_directive { boost::uint8_t minor_version; explicit minor_version_directive(boost::uint8_t minor_version) : minor_version(minor_version) {} template void operator()(basic_request& request) const { request.http_version_minor = minor_version; } }; inline minor_version_directive minor_version(boost::uint8_t minor_version_) { return minor_version_directive(minor_version_); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/status.hpp000066400000000000000000000042121256751517300302120ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; struct status_directive { boost::variant > status_; explicit status_directive(boost::uint16_t status) : status_(status) {} explicit status_directive(boost::shared_future const &status) : status_(status) {} status_directive(status_directive const &other) : status_(other.status_) {} template struct value : mpl::if_, boost::shared_future, boost::uint16_t> {}; template struct status_visitor : boost::static_visitor<> { basic_response const &response; status_visitor(basic_response const &response) : response(response) {} void operator()(typename value::type const &status_) const { response.status(status_); } template void operator()(T const &) const { // FIXME fail here! } }; template basic_response const &operator()(basic_response const &response) const { apply_visitor(status_visitor(response), status_); return response; } }; template inline status_directive const status(T const &status_) { return status_directive(status_); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/status_message.hpp000066400000000000000000000016451256751517300317250ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { BOOST_NETWORK_STRING_DIRECTIVE(status_message, status_message_, message.status_message(status_message_), message.status_message = status_message_); } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/uri.hpp000066400000000000000000000014431256751517300274710ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { BOOST_NETWORK_STRING_DIRECTIVE(uri, uri_, message.uri(uri_), message.uri = uri_); } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/directives/version.hpp000066400000000000000000000015071256751517300303600ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { BOOST_NETWORK_STRING_DIRECTIVE(version, version_, message.version(version_), message.version = version_); } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/header.hpp000066400000000000000000000056141256751517300257650ustar00rootroot00000000000000// // header.hpp // ~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2009,2010 Dean Michael Berris (mikhailberis@gmail.com) // Copyright (c) 2009 Tarroo, Inc. // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 #include #include #include #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; struct request_header_narrow { typedef std::string string_type; std::string name, value; }; struct request_header_wide { typedef std::wstring string_type; std::wstring name, value; }; template struct request_header : mpl::if_, request_header_narrow, typename mpl::if_, request_header_wide, unsupported_tag >::type> {}; inline void swap(request_header_narrow& l, request_header_narrow& r) { swap(l.name, r.name); swap(l.value, r.value); } inline void swap(request_header_wide& l, request_header_wide& r) { swap(l.name, r.name); swap(l.value, r.value); } struct response_header_narrow { typedef std::string string_type; std::string name, value; }; struct response_header_wide { typedef std::wstring string_type; std::wstring name, value; }; template struct response_header : mpl::if_, response_header_narrow, typename mpl::if_, response_header_wide, unsupported_tag >::type> {}; inline void swap(response_header_narrow& l, response_header_narrow& r) { std::swap(l.name, r.name); std::swap(l.value, r.value); } inline void swap(response_header_wide& l, response_header_wide& r) { std::swap(l.name, r.name); std::swap(l.value, r.value); } } // namespace http } // namespace network } // namespace boost BOOST_FUSION_ADAPT_STRUCT(boost::network::http::request_header_narrow, (std::string, name)(std::string, value)) BOOST_FUSION_ADAPT_STRUCT(boost::network::http::request_header_wide, (std::wstring, name)(std::wstring, value)) BOOST_FUSION_ADAPT_STRUCT(boost::network::http::response_header_narrow, (std::string, name)(std::string, value)) BOOST_FUSION_ADAPT_STRUCT(boost::network::http::response_header_wide, (std::wstring, name)(std::wstring, value)) #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/header/000077500000000000000000000000001256751517300252465ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/header/name.hpp000066400000000000000000000017711256751517300267050ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template T1 &name(std::pair const &p) { return p.first; } inline std::string const &name(request_header_narrow const &h) { return h.name; } inline std::wstring const &name(request_header_wide const &h) { return h.name; } inline std::string const &name(response_header_narrow const &h) { return h.name; } inline std::wstring const &name(response_header_wide const &h) { return h.name; } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/header/value.hpp000066400000000000000000000022611256751517300270740ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { struct request_header_narrow; struct request_header_wide; struct response_header_narrow; struct response_header_wide; template T1& value(std::pair const& p) { return p.second; } inline request_header_narrow::string_type const& value( request_header_narrow const& h) { return h.value; } inline request_header_wide::string_type const& value( request_header_wide const& h) { return h.value; } inline response_header_narrow::string_type const& value( response_header_narrow const& h) { return h.value; } inline response_header_wide::string_type const& value( response_header_wide const& h) { return h.value; } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/header_concept.hpp000066400000000000000000000016461256751517300275010ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct Header : DefaultConstructible, Assignable, CopyConstructible { BOOST_CONCEPT_USAGE(Header) { typedef typename H::string_type string_type; string_type name_ = name(header); string_type value_ = value(header); H h1, h2; swap(h1, h2); // ADL Swap! (void)name_; (void)value_; } private: H header; }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/message_base.hpp000066400000000000000000000015041256751517300271450ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct async_message; template struct message_impl; template struct message_base : mpl::if_, async_message, message_impl > {}; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/000077500000000000000000000000001256751517300257775ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/body.hpp000066400000000000000000000041061256751517300274460ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; namespace impl { template void body(basic_response &response, T const &value, mpl::false_ const &) { response << ::boost::network::body(value); } template void body(basic_response &response, T const &future, mpl::true_ const &) { response.body(future); } } template inline void body(basic_response &response, T const &value) { impl::body(response, value, is_async()); } template inline void body_impl(basic_request &request, T const &value, tags::server) { request.body = value; } template inline void body_impl(basic_request &request, T const &value, tags::client) { request << ::boost::network::body(value); } template inline void body(basic_request &request, T const &value) { body_impl(request, value, typename client_or_server::type()); } } // namespace http namespace impl { template inline void body(Message const &message, ValueType const &body_, http::tags::http_server, Async) { message.body = body_; } } /* impl */ } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/clear_headers.hpp000066400000000000000000000032441256751517300312740ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { namespace http { template inline void clear_headers_impl(basic_request& request, tags::pod) { typedef typename basic_request::headers_container_type headers_container; headers_container().swap(request.headers); } template inline void clear_headers_impl(basic_request& request, tags::normal) { request.headers(typename basic_request::headers_container_type()); } template inline void clear_headers_impl(basic_request& request, tags::client) { clear_headers_impl(request, typename pod_or_normal::type()); } template inline void clear_headers_impl(basic_request& request, tags::server) { typedef typename basic_request::headers_container_type headers_container; headers_container().swap(request.headers); } template inline void clear_headers(basic_request& request) { clear_headers_impl(request, typename client_or_server::type()); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/destination.hpp000066400000000000000000000052731256751517300310400ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; namespace impl { template void destination(basic_response &response, T const &value, mpl::false_ const &) { response << ::boost::network::destination(value); } template void destination(basic_response &response, T const &future, mpl::true_ const &) { response.destination(future); } } template inline void destination(basic_response &response, T const &value) { impl::destination(response, value, is_async()); } template struct ServerRequest; template inline void destination_impl(basic_request &request, T const &value, tags::server) { request.destination = value; } template inline void destination_impl(basic_request &request, T const &value, tags::pod) { request.destination = value; } template inline void destination_impl(basic_request &request, T const &value, tags::normal) { request.destination(value); } template inline void destination_impl(basic_request &request, T const &value, tags::client) { destination_impl(request, value, typename pod_or_normal::type()); } template inline void destination(basic_request &request, T const &value) { destination_impl(request, value, typename client_or_server::type()); } } // namespace http namespace impl { template inline void destination(Message const &message, ValueType const &destination_, http::tags::http_server, Async) { message.destination = destination_; } } /* impl */ } // namespace network } // namespace boost #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/headers.hpp000066400000000000000000000030101256751517300301150ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; namespace impl { template void headers(basic_response &response, T const &value, mpl::false_ const &) { response << headers(value); } template void headers(basic_response &response, T const &future, mpl::true_ const &) { response.headers(future); } template void headers(basic_request &request, T const &value, tags::server const &) { request.headers = value; } } template inline void headers(basic_response &response, T const &value) { impl::headers(response, value, is_async()); } template inline void headers(basic_request &request, T const &value) { impl::headers(request, value, Tag()); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/major_version.hpp000066400000000000000000000016531256751517300313720ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; template inline typename enable_if, void>::type major_version( basic_request& request, boost::uint8_t major_version_) { request.http_version_major = major_version_; } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/method.hpp000066400000000000000000000015151256751517300277720ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct basic_request; template inline typename enable_if, void>::type method( basic_request& request, typename string::type const& method_) { request.method = method_; } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/minor_version.hpp000066400000000000000000000016531256751517300314060ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; template inline typename enable_if, void>::type minor_version( basic_request& request, boost::uint8_t minor_version_) { request.http_version_minor = minor_version_; } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/source.hpp000066400000000000000000000047261256751517300300210ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template void source(basic_response &response, T const &value, mpl::false_ const &) { response << ::boost::network::source(value); } template void source(basic_response &response, T const &future, mpl::true_ const &) { response.source(future); } template void source(basic_request &request, T const &value, tags::server const &) { request.source = value; } template void source(basic_request &request, T const &value, tags::client const &) { request << ::boost::network::source(value); } } template inline void source(basic_response &response, T const &value) { impl::source(response, value, is_async()); } template inline void source_impl(basic_request &request, T const &value, tags::server) { impl::source(request, value, Tag()); } template inline void source_impl(basic_request &request, T const &value, tags::client) { impl::source(request, value, Tag()); } template inline void source(basic_request &request, T const &value) { source_impl(request, value, typename client_or_server::type()); } } // namespace http namespace impl { template inline void source(Message const &message, ValueType const &source_, http::tags::http_server const &, Async const &) { message.source = source_; } } /* impl */ } // namespace network } // namespace boost #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/status.hpp000066400000000000000000000023171256751517300300360ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template void status(basic_response &response, T const &value, mpl::false_ const &) { response << boost::network::http::status(value); } template void status(basic_response &response, T const &future, mpl::true_ const &) { response.status(future); } } // namespace impl template void status(basic_response &response, T const &value) { impl::status(response, value, is_async()); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/status_message.hpp000066400000000000000000000024471256751517300315460ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template void status_message(basic_response &response, T const &value, mpl::false_ const &) { response << boost::network::http::status_message(value); } template void status_message(basic_response &response, T const &future, mpl::true_ const &) { response.status_message(future); } } // namespace impl template void status_message(basic_response &response, T const &value) { impl::status_message(response, value, is_async()); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/uri.hpp000066400000000000000000000014601256751517300273100ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct basic_request; template void uri(basic_request& request, T const& value) { request.uri(value); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/modifiers/version.hpp000066400000000000000000000024431256751517300302000ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template void version(basic_response &response, T const &value, mpl::false_ const &) { response << boost::network::http::version(value); } template void version(basic_response &response, T const &future, mpl::true_ const &) { response.version(future); } } // namespace impl template void version(basic_response &response, T const &value) { impl::version(response, value, is_async()); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/traits/000077500000000000000000000000001256751517300253245ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/traits/status.hpp000066400000000000000000000016571256751517300273710ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_HPP_20100903 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { namespace traits { template struct unsupported_tag; template struct status : mpl::if_< is_async, boost::shared_future, typename mpl::if_, boost::uint16_t, unsupported_tag >::type> {}; } /* traits */ } /* http */ } /* network */ } /* boost */ #endif cpp-netlib-0.11.2-final/boost/network/protocol/http/message/traits/status_message.hpp000066400000000000000000000023041256751517300310630ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_MESSAGE_HPP_20100903 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_MESSAGE_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { namespace traits { template struct unsupported_tag; template struct status_message : mpl::if_< is_async, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, typename string::type, unsupported_tag >::type> {}; } /* traits */ } /* http */ } /* network */ } /* boost */ #endif cpp-netlib-0.11.2-final/boost/network/protocol/http/message/traits/version.hpp000066400000000000000000000026511256751517300275260ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_VERSION_HPP_20100903 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_VERSION_HPP_20100903 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { namespace traits { template struct unsupported_tag; template struct version { typedef unsupported_tag type; }; template struct version >::type> { typedef boost::shared_future::type> type; }; template struct version< Message, typename enable_if< mpl::or_, is_default_string, is_default_wstring > >::type> { typedef typename string::type type; }; } /* traits */ } /* http */ } /* network */ } /* boost */ #endif cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/000077500000000000000000000000001256751517300256615ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/anchor.hpp000066400000000000000000000020641256751517300276460ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct anchor_wrapper { basic_request const& message_; anchor_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.anchor(); } }; } template inline impl::anchor_wrapper anchor(basic_request const& request) { return impl::anchor_wrapper(request); } } // namespace http } // namespace network } // nmaespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/body.hpp000066400000000000000000000034401256751517300273300ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; namespace impl { template struct body_wrapper { typedef typename string::type string_type; Message const& message_; explicit body_wrapper(Message const& message) : message_(message) {} body_wrapper(body_wrapper const& other) : message_(other.message_) {} operator string_type() const { return message_.body(); } size_t size() const { return message_.body().size(); } boost::iterator_range range() const { return boost::make_iterator_range(message_.body()); } }; template inline std::ostream& operator<<(std::ostream& os, body_wrapper const& body) { os << static_cast::string_type>(body); return os; } } // namespace impl template inline typename impl::body_wrapper > body( basic_response const& message) { return impl::body_wrapper >(message); } template inline typename impl::body_wrapper > body( basic_request const& message) { return impl::body_wrapper >(message); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/destination.hpp000066400000000000000000000015121256751517300307120ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 // Copyright 2010 (c) Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; template struct Request; template struct Response; BOOST_NETWORK_DEFINE_HTTP_WRAPPER(destination, destination, destination); } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/headers.hpp000066400000000000000000000071011256751517300300040ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct headers_range { typedef typename headers_container::type headers_container_type; typedef typename boost::iterator_range< typename headers_container_type::const_iterator> type; }; template struct basic_request; template struct basic_response; namespace impl { template struct request_headers_wrapper { typedef typename string::type string_type; typedef typename headers_range >::type range_type; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::const_iterator const_iterator; typedef typename headers_container_type::iterator iterator; explicit request_headers_wrapper(basic_request const& message) : message_(message) {} range_type operator[](string_type const& key) const { return message_.headers().equal_range(key); } typename headers_container_type::size_type count(string_type const& key) const { return message_.headers().count(key); } const_iterator begin() const { return message_.headers().begin(); } const_iterator end() const { return message_.headers().end(); } operator range_type() { return make_iterator_range(message_.headers().begin(), message_.headers().end()); } operator headers_container_type() { return message_.headers(); } private: basic_request const& message_; }; template struct response_headers_wrapper { typedef typename string::type string_type; typedef typename headers_range >::type range_type; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::const_iterator const_iterator; typedef typename headers_container_type::iterator iterator; explicit response_headers_wrapper(basic_response const& message) : message_(message) {} range_type operator[](string_type const& key) const { return message_.headers().equal_range(key); } typename headers_container_type::size_type count(string_type const& key) const { return message_.headers().count(key); } const_iterator begin() const { return message_.headers().begin(); } const_iterator end() const { return message_.headers().end(); } operator range_type() { return make_iterator_range(message_.headers().begin(), message_.headers().end()); } operator headers_container_type() { return message_.headers(); } private: basic_response const& message_; }; } // namespace impl template inline impl::request_headers_wrapper headers( basic_request const& request_) { return impl::request_headers_wrapper(request_); } template inline impl::response_headers_wrapper headers( basic_response const& response_) { return impl::response_headers_wrapper(response_); } } // namepace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/helper.hpp000066400000000000000000000074701256751517300276610ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #ifndef BOOST_NETWORK_DEFINE_HTTP_WRAPPER #define BOOST_NETWORK_DEFINE_HTTP_WRAPPER(name, accessor, pod_field) \ struct name##_pod_accessor { \ protected: \ template \ typename Message::string_type const& get_value(Message const& message) \ const { \ return message.pod_field; \ } \ }; \ \ struct name##_member_accessor { \ protected: \ template \ typename Message::string_type get_value(Message const& message) const { \ return message.accessor(); \ } \ }; \ \ template \ struct name##_wrapper_impl \ : mpl::if_, name##_pod_accessor, \ name##_member_accessor> {}; \ \ template \ struct name##_wrapper : name##_wrapper_impl::type { \ typedef typename string::type string_type; \ Message const& message_; \ name##_wrapper(Message const& message) : message_(message) {} \ name##_wrapper(name##_wrapper const& other) : message_(other.message_) {} \ operator string_type() const { return this->get_value(message_); } \ }; \ \ template \ inline name##_wrapper > const name( \ basic_response const& message) { \ return name##_wrapper >(message); \ } \ \ template \ inline name##_wrapper > const name( \ basic_request const& message) { \ return name##_wrapper >(message); \ } #endif /* BOOST_NETWORK_DEFINE_HTTP_WRAPPER */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/host.hpp000066400000000000000000000020131256751517300273430ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct host_wrapper { basic_request const& message_; host_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.host(); } }; } template inline impl::host_wrapper host(basic_request const& request) { return impl::host_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/major_version.hpp000066400000000000000000000022401256751517300312450ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; template struct major_version_wrapper { basic_request const& request; explicit major_version_wrapper(basic_request const& request) : request(request) {} operator boost::uint8_t() { return request.http_version_major; } }; template inline typename enable_if, major_version_wrapper >::type major_version(basic_request const& request) { return major_version_wrapper(request); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/method.hpp000066400000000000000000000021741256751517300276560ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct basic_request; template struct method_wrapper { explicit method_wrapper(basic_request const& message) : message_(message) {} basic_request const& message_; typedef typename basic_request::string_type string_type; operator string_type() { return message_.method; } }; template inline typename enable_if, typename string::type>::type method(basic_request const& message) { return method_wrapper(message); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/minor_version.hpp000066400000000000000000000022401256751517300312610ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; template struct minor_version_wrapper { basic_request const& request; explicit minor_version_wrapper(basic_request const& request) : request(request) {} operator boost::uint8_t() { return request.http_version_minor; } }; template inline typename enable_if, minor_version_wrapper >::type minor_version(basic_request const& request) { return minor_version_wrapper(request); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/path.hpp000066400000000000000000000020131256751517300273220ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct path_wrapper { basic_request const& message_; path_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.path(); } }; } template inline impl::path_wrapper path(basic_request const& request) { return impl::path_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/port.hpp000066400000000000000000000033171256751517300273620ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 // Copyright 2010, 2014 Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Copyright 2014 Google, Inc. // Copyright 2014 Jussi Lyytinen // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct port_wrapper { basic_request const& message_; port_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::port_type port_type; operator port_type() const { return message_.port(); } #if (_MSC_VER >= 1600 && BOOST_VERSION > 105500) // Because of a breaking change in Boost 1.56 to boost::optional, implicit // conversions no longer work correctly with MSVC. The conversion therefore // has to be done explicitly with as_optional(). boost::optional as_optional() const { return uri::port_us(message_.uri()); } #else operator boost::optional() const { return uri::port_us(message_.uri()); } #endif }; } // namespace impl template inline impl::port_wrapper port(basic_request const& request) { return impl::port_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/protocol.hpp000066400000000000000000000021061256751517300302320ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct protocol_wrapper { basic_request const& message_; protocol_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.protocol(); } }; } template inline impl::protocol_wrapper protocol(basic_request const& request) { return impl::protocol_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/query.hpp000066400000000000000000000021031256751517300275330ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct query_wrapper { basic_request const& message_; query_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.query(); } }; } // namespace impl template inline impl::query_wrapper query(basic_request const& request) { return impl::query_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/ready.hpp000066400000000000000000000025701256751517300275020ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct async_message; namespace impl { template struct ready_wrapper : boost::network::detail::wrapper_base_const > { typedef boost::network::detail::wrapper_base_const > wrapper_base; explicit ready_wrapper(async_message const& message) : wrapper_base(message) {} operator bool() { return wrapper_base::_message.version_.is_ready() && wrapper_base::_message.status_.is_ready() && wrapper_base::_message.status_message_.is_ready() && wrapper_base::_message.headers_.is_ready() && wrapper_base::_message.body_.is_ready(); } }; } // namespace impl template inline bool ready(async_message const& message) { return impl::ready_wrapper(message); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/source.hpp000066400000000000000000000013751256751517300277000ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct basic_response; template struct basic_request; BOOST_NETWORK_DEFINE_HTTP_WRAPPER(source, source, source); } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/status.hpp000066400000000000000000000022731256751517300277210ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template struct status_wrapper { basic_response const& response_; explicit status_wrapper(basic_response const& response) : response_(response) {} status_wrapper(status_wrapper const& other) : response_(other.response_) {} operator boost::uint16_t() { return response_.status(); } }; } // namespace impl template struct Response; template inline impl::status_wrapper status(basic_response const& response) { return impl::status_wrapper(response); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/status_message.hpp000066400000000000000000000031141256751517300314200ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Copyright 2014 (c) Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template struct status_message_wrapper { typedef typename string::type string_type; basic_response const& response_; explicit status_message_wrapper(basic_response const& response) : response_(response) {} status_message_wrapper(status_message_wrapper const& other) : response_(other.response_) {} operator string_type() const { return response_.status_message(); } }; template inline std::ostream& operator<<(std::ostream& os, const status_message_wrapper& wrapper) { return os << static_cast::type>(wrapper); } } // namespace impl template inline impl::status_message_wrapper status_message( basic_response const& response) { return impl::status_message_wrapper(response); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_STATUS_MESSAGE_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/uri.hpp000066400000000000000000000022061256751517300271710ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { template struct basic_request; namespace impl { template struct uri_wrapper { basic_request const& message_; uri_wrapper(basic_request const& message) : message_(message) {} typedef typename basic_request::string_type string_type; operator string_type() { return message_.uri().raw(); } operator boost::network::uri::uri() { return message_.uri(); } }; } template inline impl::uri_wrapper uri(basic_request const& request) { return impl::uri_wrapper(request); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 cpp-netlib-0.11.2-final/boost/network/protocol/http/message/wrappers/version.hpp000066400000000000000000000022621256751517300300610ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace boost { namespace network { namespace http { template struct basic_response; namespace impl { template struct version_wrapper { typedef typename string::type string_type; basic_response const& response_; explicit version_wrapper(basic_response const& response) : response_(response) {} version_wrapper(version_wrapper const& other) : response_(other.response_) {} operator string_type() { return response_.version(); } }; } // namespace impl template inline impl::version_wrapper version(basic_response const& response) { return impl::version_wrapper(response); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/parser.hpp000066400000000000000000000246441256751517300244110ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { // forward declarations used to finish HTTP requests template class basic_request; // forward declarations used to finish HTTP requests template class basic_response; /// an incremental HTTP 1.0/1.1 protocol parser template > class basic_parser : private boost::noncopyable { public: // import types from ParserTraits template typedef ParserTraits traits_type; typedef typename string::type string_type; // default destructor virtual ~basic_parser() {} /** * creates a new HTTP protocol parser * * @param is_request if true, the message is parsed as an HTTP request; * if false, the message is parsed as an HTTP response */ basic_parser(const bool is_request) : m_is_request(is_request), m_read_ptr(NULL), m_read_end_ptr(NULL), m_headers_parse_state(is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H), m_chunked_content_parse_state(PARSE_CHUNK_SIZE_START), m_status_code(0), m_bytes_last_read(0), m_bytes_total_read(0) {} /** * parses an HTTP message up to the end of the headers using bytes * available in the read buffer * * @param http_msg the HTTP message object to populate from parsing * * @return boost::tribool result of parsing: * false = message has an error, * true = finished parsing HTTP headers, * indeterminate = not yet finished parsing HTTP *headers */ boost::tribool parse_http_headers(basic_message& http_msg); /** * parses a chunked HTTP message-body using bytes available in the read *buffer * * @param chunk_buffers buffers to be populated from parsing chunked *content * * @return boost::tribool result of parsing: * false = message has an error, * true = finished parsing message, * indeterminate = message is not yet finished */ boost::tribool parse_chunks(types::chunk_cache_t& chunk_buffers); /** * prepares the payload content buffer and consumes any content *remaining * in the parser's read buffer * * @param http_msg the HTTP message object to consume content for * @return unsigned long number of content bytes consumed, if any */ std::size_t consume_content(basic_message& http_msg); /** * consume the bytes available in the read buffer, converting them into * the next chunk for the HTTP message * * @param chunk_buffers buffers to be populated from parsing chunked *content * @return unsigned long number of content bytes consumed, if any */ std::size_t consume_content_as_next_chunk( types::chunk_cache_t& chunk_buffers); /** * finishes parsing an HTTP request message (copies over request-only *data) * * @param http_request the HTTP request object to finish */ void finish(basic_request& http_request); /** * finishes an HTTP response message (copies over response-only data) * * @param http_request the HTTP response object to finish */ void finish(basic_response& http_response); /** * resets the location and size of the read buffer * * @param ptr pointer to the first bytes available to be read * @param len number of bytes available to be read */ inline void set_read_buffer(const char* ptr, std::size_t len) { m_read_ptr = ptr; m_read_end_ptr = ptr + len; } /** * saves the current read position bookmark * * @param read_ptr points to the next character to be consumed in the *read_buffer * @param read_end_ptr points to the end of the read_buffer (last byte + *1) */ inline void save_read_position(const char*& read_ptr, const char*& read_end_ptr) const { read_ptr = m_read_ptr; read_end_ptr = m_read_end_ptr; } /// resets the parser to its initial state inline void reset(void); /// returns true if there are no more bytes available in the read buffer inline bool eof(void) const { return m_read_ptr == NULL || m_read_ptr >= m_read_end_ptr; } /// returns the number of bytes read during the last parse operation inline std::size_t gcount(void) const { return m_bytes_last_read; } /// returns the total number of bytes read while parsing the HTTP /// message inline std::size_t bytes_read(void) const { return m_bytes_total_read; } /// returns the number of bytes available in the read buffer inline std::size_t bytes_available(void) const { return (eof() ? 0 : (m_read_end_ptr - m_read_ptr)); } protected: /** * parse key-value pairs out of a url-encoded string * (i.e. this=that&a=value) * * @param params container for key-values string pairs * @param ptr points to the start of the encoded string * @param len length of the encoded string, in bytes * * @return bool true if successful */ static bool parse_url_encoded(types::query_params& params, const char* ptr, const std::size_t len); /** * parse key-value pairs out of a "Cookie" request header * (i.e. this=that; a=value) * * @param params container for key-values string pairs * @param cookie_header header string to be parsed * * @return bool true if successful */ static bool parse_cookie_header(types::cookie_params& params, const string_type& cookie_header); /// true if the message is an HTTP request; false if it is an HTTP /// response const bool m_is_request; /// points to the next character to be consumed in the read_buffer const char* m_read_ptr; /// points to the end of the read_buffer (last byte + 1) const char* m_read_end_ptr; private: // returns true if the argument is a special character inline static bool is_special(int c) { switch (c) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case ':': case '\\': case '"': case '/': case '[': case ']': case '?': case '=': case '{': case '}': case ' ': case '\t': return true; default: return false; } } // returns true if the argument is a character inline static bool is_char(int c) { return (c >= 0 && c <= 127); } // returns true if the argument is a control character inline static bool is_control(int c) { return ((c >= 0 && c <= 31) || c == 127); } // returns true if the argument is a digit inline static bool is_digit(int c) { return (c >= '0' && c <= '9'); } // returns true if the argument is a hexadecimal digit inline static bool is_hex_digit(int c) { return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } /// state used to keep track of where we are in parsing the HTTP headers enum headers_parse_state_t { PARSE_METHOD_START, PARSE_METHOD, PARSE_URI_STEM, PARSE_URI_QUERY, PARSE_HTTP_VERSION_H, PARSE_HTTP_VERSION_T_1, PARSE_HTTP_VERSION_T_2, PARSE_HTTP_VERSION_P, PARSE_HTTP_VERSION_SLASH, PARSE_HTTP_VERSION_MAJOR_START, PARSE_HTTP_VERSION_MAJOR, PARSE_HTTP_VERSION_MINOR_START, PARSE_HTTP_VERSION_MINOR, PARSE_STATUS_CODE_START, PARSE_STATUS_CODE, PARSE_STATUS_MESSAGE, PARSE_EXPECTING_NEWLINE, PARSE_EXPECTING_CR, PARSE_HEADER_WHITESPACE, PARSE_HEADER_START, PARSE_HEADER_NAME, PARSE_SPACE_BEFORE_HEADER_VALUE, PARSE_HEADER_VALUE, PARSE_EXPECTING_FINAL_NEWLINE, PARSE_EXPECTING_FINAL_CR }; /// state used to keep track of where we are in parsing chunked content enum chunked_content_parse_state_t { PARSE_CHUNK_SIZE_START, PARSE_CHUNK_SIZE, PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE, PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE, PARSE_CHUNK, PARSE_EXPECTING_CR_AFTER_CHUNK, PARSE_EXPECTING_LF_AFTER_CHUNK, PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK, PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK }; /// the current state of parsing HTTP headers headers_parse_state_t m_headers_parse_state; /// the current state of parsing chunked content chunked_content_parse_state_t m_chunked_content_parse_state; /// Used for parsing the HTTP response status code boost::uint16_t m_status_code; /// Used for parsing the HTTP response status message string_type m_status_message; /// Used for parsing the request method string_type m_method; /// Used for parsing the name of resource requested string_type m_resource; /// Used for parsing the query string portion of a URI string_type m_query_string; /// Used for parsing the name of HTTP headers string_type m_header_name; /// Used for parsing the value of HTTP headers string_type m_header_value; /// Used for parsing the chunk size string_type m_chunk_size_str; /// Used for parsing the current chunk std::vector m_current_chunk; /// number of bytes in the chunk currently being parsed std::size_t m_size_of_current_chunk; /// number of bytes read so far in the chunk currently being parsed std::size_t m_bytes_read_in_current_chunk; /// number of bytes read during last parse operation std::size_t m_bytes_last_read; /// total number of bytes read while parsing the HTTP message std::size_t m_bytes_total_read; }; /// typedef for the default HTTP protocol parser implementation typedef basic_parser parser; }; // namespace http }; // namespace network }; // namespace boost // import implementation file #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/parser/000077500000000000000000000000001256751517300236665ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/parser/incremental.hpp000066400000000000000000000222021256751517300266760ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 // Copyright Dean Michael Berris 2010. // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct response_parser { enum state_t { http_response_begin, http_version_h, http_version_t1, http_version_t2, http_version_p, http_version_slash, http_version_major, http_version_dot, http_version_minor, http_version_done, http_status_digit, http_status_done, http_status_message_char, http_status_message_cr, http_status_message_done, http_header_name_char, http_header_colon, http_header_value_char, http_header_line_cr, http_header_line_done, http_headers_end_cr, http_headers_done }; explicit response_parser(state_t state = http_response_begin) : state_(state) {} response_parser(response_parser const& other) : state_(other.state_) {} ~response_parser() {} void swap(response_parser& other) { std::swap(other.state_, this->state_); } response_parser& operator=(response_parser rhs) { rhs.swap(*this); return *this; } template fusion::tuple > parse_until(state_t stop_state, Range& range_) { logic::tribool parsed_ok(logic::indeterminate); typename Range::const_iterator start = boost::begin(range_), current = start, end = boost::end(range_); boost::iterator_range local_range = boost::make_iterator_range(start, end); while (!boost::empty(local_range) && indeterminate(parsed_ok)) { current = boost::begin(local_range); if (state_ == stop_state) { parsed_ok = true; } else { switch (state_) { case http_response_begin: if (*current == ' ' || *current == '\r' || *current == '\n') { // skip valid leading whitespace ++start; ++current; } else if (*current == 'H') { state_ = http_version_h; start = current; ++current; } else { parsed_ok = false; } break; case http_version_h: if (*current == 'T') { state_ = http_version_t1; ++current; } else { parsed_ok = false; } break; case http_version_t1: if (*current == 'T') { state_ = http_version_t2; ++current; } else { parsed_ok = false; } break; case http_version_t2: if (*current == 'P') { state_ = http_version_p; ++current; } else { parsed_ok = false; } break; case http_version_p: if (*current == '/') { state_ = http_version_slash; ++current; } else { parsed_ok = false; } break; case http_version_slash: if (algorithm::is_digit()(*current)) { state_ = http_version_major; ++current; } else { parsed_ok = false; } break; case http_version_major: if (*current == '.') { state_ = http_version_dot; ++current; } else { parsed_ok = false; } break; case http_version_dot: if (algorithm::is_digit()(*current)) { state_ = http_version_minor; ++current; } else { parsed_ok = false; } break; case http_version_minor: if (*current == ' ') { state_ = http_version_done; ++current; } else { parsed_ok = false; } break; case http_version_done: if (algorithm::is_digit()(*current)) { state_ = http_status_digit; ++current; } else { parsed_ok = false; } break; case http_status_digit: if (algorithm::is_digit()(*current)) { ++current; } else if (*current == ' ') { state_ = http_status_done; ++current; } else if (*current == '\r' || *current == '\n') { state_ = http_status_done; } else { parsed_ok = false; } break; case http_status_done: if (*current == ' ') { ++current; } else if (*current == '\r') { state_ = http_status_message_cr; ++current; } else if (*current == '\n') { state_ = http_status_message_done; ++current; } else { state_ = http_status_message_char; ++current; } break; case http_status_message_char: if (*current == '\r') { state_ = http_status_message_cr; ++current; } else if (*current == '\n') { state_ = http_status_message_done; ++current; } else { ++current; } break; case http_status_message_cr: if (*current == '\n') { state_ = http_status_message_done; ++current; } else { parsed_ok = false; } break; case http_status_message_done: case http_header_line_done: if (*current == ' ') { ++current; } else if (algorithm::is_alnum()(*current) || algorithm::is_punct()(*current)) { state_ = http_header_name_char; ++current; } else if (*current == '\r') { state_ = http_headers_end_cr; ++current; } else if (*current == '\n') { state_ = http_headers_done; ++current; } else { parsed_ok = false; } break; case http_header_name_char: if (*current == ':') { state_ = http_header_colon; ++current; } else if (*current == '\r') { state_ = http_header_line_cr; ++current; } else if (*current == '\n') { state_ = http_header_line_done; ++current; } else if (algorithm::is_alnum()(*current) || algorithm::is_space()(*current) || algorithm::is_punct()(*current)) { ++current; } else { parsed_ok = false; } break; case http_header_colon: if (*current == '\r') { state_ = http_header_line_cr; ++current; } else if (*current == '\n') { state_ = http_header_line_done; ++current; } else if (algorithm::is_space()(*current)) { ++current; } else { state_ = http_header_value_char; ++current; } break; case http_header_value_char: if (*current == '\r') { state_ = http_header_line_cr; ++current; } else if (*current == '\n') { state_ = http_header_line_done; ++current; } else { ++current; } break; case http_header_line_cr: if (*current == '\n') { state_ = http_header_line_done; ++current; } else { parsed_ok = false; } break; case http_headers_end_cr: if (*current == '\n') { state_ = http_headers_done; ++current; } else { parsed_ok = false; } break; default: parsed_ok = false; } } local_range = boost::make_iterator_range(current, end); } if (state_ == stop_state) parsed_ok = true; return fusion::make_tuple(parsed_ok, boost::make_iterator_range(start, current)); } state_t state() { return state_; } void reset(state_t new_state = http_response_begin) { state_ = new_state; } private: state_t state_; }; } /* http */ } /* network */ } /* boost */ #endif cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/000077500000000000000000000000001256751517300242015ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/async_connection.hpp000066400000000000000000000112031256751517300302430ustar00rootroot00000000000000#ifndef BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 #define BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct async_connection_policy : resolver_policy::type { protected: typedef typename string::type string_type; typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename resolver_base::resolve_function resolve_function; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; struct connection_impl { connection_impl(bool follow_redirect, bool always_verify_peer, resolve_function resolve, resolver_type& resolver, bool https, int timeout, optional const& certificate_filename, optional const& verify_path, optional const& certificate_file, optional const& private_key_file, optional const& ciphers, long ssl_options) { pimpl = impl::async_connection_base< Tag, version_major, version_minor>::new_connection(resolve, resolver, follow_redirect, always_verify_peer, https, timeout, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options); } basic_response send_request(string_type const& method, basic_request const& request_, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { return pimpl->start(request_, method, get_body, callback, generator); } private: shared_ptr > pimpl; }; typedef boost::shared_ptr connection_ptr; connection_ptr get_connection( resolver_type& resolver, basic_request const& request_, bool always_verify_peer, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) { string_type protocol_ = protocol(request_); connection_ptr connection_(new connection_impl( follow_redirect_, always_verify_peer, boost::bind(&async_connection_policy::resolve, this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>(), boost::arg<4>()), resolver, boost::iequals(protocol_, string_type("https")), timeout_, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); return connection_; } void cleanup() {} async_connection_policy(bool cache_resolved, bool follow_redirect, int timeout) : resolver_base(cache_resolved), follow_redirect_(follow_redirect), timeout_(timeout) {} bool follow_redirect_; int timeout_; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_ cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/async_resolver.hpp000066400000000000000000000066111256751517300277540ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 #define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { namespace policies { template struct async_resolver : boost::enable_shared_from_this > { typedef typename resolver::type resolver_type; typedef typename resolver_type::iterator resolver_iterator; typedef typename resolver_type::query resolver_query; typedef std::pair resolver_iterator_pair; typedef typename string::type string_type; typedef boost::unordered_map endpoint_cache; typedef boost::function< void(boost::system::error_code const &, resolver_iterator_pair)> resolve_completion_function; typedef boost::function resolve_function; protected: bool cache_resolved_; endpoint_cache endpoint_cache_; boost::shared_ptr service_; boost::shared_ptr resolver_strand_; explicit async_resolver(bool cache_resolved) : cache_resolved_(cache_resolved), endpoint_cache_() {} void resolve(resolver_type &resolver_, string_type const &host, boost::uint16_t port, resolve_completion_function once_resolved) { if (cache_resolved_) { typename endpoint_cache::iterator iter = endpoint_cache_.find(boost::to_lower_copy(host)); if (iter != endpoint_cache_.end()) { boost::system::error_code ignored; once_resolved(ignored, iter->second); return; } } typename resolver_type::query q(host, lexical_cast(port)); resolver_.async_resolve(q, resolver_strand_->wrap(boost::bind( &async_resolver::handle_resolve, async_resolver::shared_from_this(), boost::to_lower_copy(host), once_resolved, boost::asio::placeholders::error, boost::asio::placeholders::iterator))); } void handle_resolve(string_type const &host, resolve_completion_function once_resolved, boost::system::error_code const &ec, resolver_iterator endpoint_iterator) { typename endpoint_cache::iterator iter; bool inserted = false; if (!ec && cache_resolved_) { boost::fusion::tie(iter, inserted) = endpoint_cache_.insert(std::make_pair( host, std::make_pair(endpoint_iterator, resolver_iterator()))); once_resolved(ec, iter->second); } else { once_resolved(ec, std::make_pair(endpoint_iterator, resolver_iterator())); } } }; } // namespace policies } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/pooled_connection.hpp000066400000000000000000000237121256751517300304200ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 // Copyright 2013 Google, Inc. // Copyright 2009 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #ifndef BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT #define BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT 5 #endif // BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT namespace boost { namespace network { namespace http { template struct pooled_connection_policy : resolver_policy::type { protected: typedef typename string::type string_type; typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; void cleanup() { host_connection_map().swap(host_connections); } struct connection_impl { typedef function( resolver_type&, basic_request const&, optional const&, optional const&, optional const&, optional const&, optional const&)> get_connection_function; connection_impl( resolver_type& resolver, bool follow_redirect, string_type const& host, string_type const& port, resolver_function_type resolve, get_connection_function get_connection, bool https, bool always_verify_peer, int timeout, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) : pimpl(impl::sync_connection_base:: new_connection(resolver, resolve, https, always_verify_peer, timeout, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)), resolver_(resolver), connection_follow_redirect_(follow_redirect), get_connection_(get_connection), certificate_filename_(certificate_filename), verify_path_(verify_path), certificate_file_(certificate_file), private_key_file_(private_key_file), ciphers_(ciphers), ssl_options_(ssl_options) { // TODO(dberris): review parameter necessity. (void)host; (void)port; } basic_response send_request(string_type const& method, basic_request request_, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { return send_request_impl(method, request_, get_body, callback, generator); } private: basic_response send_request_impl( string_type const& method, basic_request request_, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { // TODO(dberris): review parameter necessity. (void)callback; boost::uint8_t count = 0; bool retry = false; do { if (count >= BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT) boost::throw_exception(std::runtime_error( "Redirection exceeds maximum redirect count.")); basic_response response_; // check if the socket is open first if (!pimpl->is_open()) { pimpl->init_socket(request_.host(), lexical_cast(request_.port())); } response_ = basic_response(); response_ << ::boost::network::source(request_.host()); pimpl->send_request_impl(method, request_, generator); boost::asio::streambuf response_buffer; try { pimpl->read_status(response_, response_buffer); } catch (boost::system::system_error& e) { if (!retry && e.code() == boost::asio::error::eof) { retry = true; pimpl->init_socket(request_.host(), lexical_cast(request_.port())); continue; } throw; // it's a retry, and there's something wrong. } pimpl->read_headers(response_, response_buffer); if (get_body && response_.status() != 304 && (response_.status() != 204) && !(response_.status() >= 100 && response_.status() <= 199)) { pimpl->read_body(response_, response_buffer); } typename headers_range >::type connection_range = headers(response_)["Connection"]; if (version_major == 1 && version_minor == 1 && !boost::empty(connection_range) && boost::begin(connection_range)->second == string_type("close")) { pimpl->close_socket(); } else if (version_major == 1 && version_minor == 0) { pimpl->close_socket(); } if (connection_follow_redirect_) { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range >::type location_range = headers(response_)["Location"]; typename range_iterator< typename headers_range >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); connection_ptr connection_; connection_ = get_connection_( resolver_, request_, certificate_filename_, verify_path_, certificate_file_, private_key_file_, ciphers_); ++count; continue; } else boost::throw_exception(std::runtime_error( "Location header not defined in redirect response.")); } } return response_; } while (true); } shared_ptr > pimpl; resolver_type& resolver_; bool connection_follow_redirect_; get_connection_function get_connection_; optional certificate_filename_; optional verify_path_; optional certificate_file_; optional private_key_file_; optional ciphers_; long ssl_options_; }; typedef shared_ptr connection_ptr; typedef unordered_map host_connection_map; host_connection_map host_connections; bool follow_redirect_; int timeout_; connection_ptr get_connection( resolver_type& resolver, basic_request const& request_, bool always_verify_peer, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional()) { string_type index = (request_.host() + ':') + lexical_cast(request_.port()); connection_ptr connection_; typename host_connection_map::iterator it = host_connections.find(index); if (it == host_connections.end()) { connection_.reset(new connection_impl( resolver, follow_redirect_, request_.host(), lexical_cast(request_.port()), boost::bind(&pooled_connection_policy::resolve, this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>()), boost::bind(&pooled_connection_policy::get_connection, this, boost::arg<1>(), boost::arg<2>(), always_verify_peer, boost::arg<3>(), boost::arg<4>(), boost::arg<5>(), boost::arg<6>(), boost::arg<7>()), boost::iequals(request_.protocol(), string_type("https")), always_verify_peer, timeout_, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, 0)); host_connections.insert(std::make_pair(index, connection_)); return connection_; } return it->second; } pooled_connection_policy(bool cache_resolved, bool follow_redirect, int timeout) : resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect), timeout_(timeout) {} }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/simple_connection.hpp000066400000000000000000000147541256751517300304350ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 // Copyright 2013 Google, Inc. // Copyright 2009 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct simple_connection_policy : resolver_policy::type { protected: typedef typename string::type string_type; typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; typedef function const&, system::error_code const&)> body_callback_function_type; typedef function body_generator_function_type; struct connection_impl { connection_impl( resolver_type& resolver, bool follow_redirect, bool always_verify_peer, string_type const& hostname, string_type const& port, resolver_function_type resolve, bool https, int timeout, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) : pimpl(), follow_redirect_(follow_redirect) { // TODO(dberris): review parameter necessity. (void)hostname; (void)port; pimpl.reset(impl::sync_connection_base< Tag, version_major, version_minor>::new_connection(resolver, resolve, https, always_verify_peer, timeout, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); } basic_response send_request(string_type const& method, basic_request request_, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { // TODO(dberris): review parameter necessity. (void)callback; basic_response response_; do { pimpl->init_socket(request_.host(), lexical_cast(request_.port())); pimpl->send_request_impl(method, request_, generator); response_ = basic_response(); response_ << network::source(request_.host()); boost::asio::streambuf response_buffer; pimpl->read_status(response_, response_buffer); pimpl->read_headers(response_, response_buffer); if (get_body) pimpl->read_body(response_, response_buffer); if (follow_redirect_) { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range >::type location_range = headers(response_)["Location"]; typename range_iterator< typename headers_range >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); } else throw std::runtime_error( "Location header not defined in redirect response."); } else break; } else break; } while (true); return response_; } private: shared_ptr > pimpl; bool follow_redirect_; }; typedef boost::shared_ptr connection_ptr; connection_ptr get_connection( resolver_type& resolver, basic_request const& request_, bool always_verify_peer, optional const& certificate_filename = optional(), optional const& verify_path = optional(), optional const& certificate_file = optional(), optional const& private_key_file = optional(), optional const& ciphers = optional(), long ssl_options = 0) { connection_ptr connection_(new connection_impl( resolver, follow_redirect_, always_verify_peer, request_.host(), lexical_cast(request_.port()), boost::bind(&simple_connection_policy::resolve, this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>()), boost::iequals(request_.protocol(), string_type("https")), timeout_, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); return connection_; } void cleanup() {} simple_connection_policy(bool cache_resolved, bool follow_redirect, int timeout) : resolver_base(cache_resolved), follow_redirect_(follow_redirect), timeout_(timeout) {} // member variables bool follow_redirect_; int timeout_; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/policies/sync_resolver.hpp000066400000000000000000000046701256751517300276160ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 // Copyright Dean Michael Berris 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { namespace policies { template struct sync_resolver { typedef typename resolver::type resolver_type; typedef typename resolver_type::iterator resolver_iterator; typedef typename resolver_type::query resolver_query; typedef std::pair resolver_iterator_pair; protected: typedef typename string::type string_type; typedef boost::unordered_map resolved_cache; resolved_cache endpoint_cache_; bool cache_resolved_; sync_resolver(bool cache_resolved) : cache_resolved_(cache_resolved) {} resolver_iterator_pair resolve(resolver_type& resolver_, string_type const& hostname, string_type const& port) { if (cache_resolved_) { typename resolved_cache::iterator cached_iterator = endpoint_cache_.find(hostname); if (cached_iterator == endpoint_cache_.end()) { bool inserted = false; boost::fusion::tie(cached_iterator, inserted) = endpoint_cache_.insert(std::make_pair( boost::to_lower_copy(hostname), std::make_pair( resolver_.resolve(resolver_query( hostname, port, resolver_query::numeric_service)), resolver_iterator()))); }; return cached_iterator->second; }; return std::make_pair(resolver_.resolve(resolver_query( hostname, port, resolver_query::numeric_service)), resolver_iterator()); }; }; } // namespace policies } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/request.hpp000066400000000000000000000062361256751517300246020ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __NETWORK_PROTOCOL_HTTP_REQUEST_20070908_1_HPP__ #define __NETWORK_PROTOCOL_HTTP_REQUEST_20070908_1_HPP__ // Implement the HTTP Request Object #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // forward declarations namespace boost { namespace network { namespace http { template struct basic_request; } // namespace http } // namespace network } // namespace boost #include namespace boost { namespace network { namespace http { template basic_request& operator<<(basic_request& message, Directive const& directive) { directive(message); return message; } } // namespace http } // namespace network } // namespace boost #include #endif // __NETWORK_PROTOCOL_HTTP_REQUEST_20070908-1_HPP__ cpp-netlib-0.11.2-final/boost/network/protocol/http/request_concept.hpp000066400000000000000000000061661256751517300263170ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace http { template struct ServerRequest { typedef typename R::string_type string_type; typedef typename R::tag tag; typedef typename R::headers_container_type headers_container_type; BOOST_CONCEPT_USAGE(ServerRequest) { string_type source_, method_, destination_; boost::uint8_t major_version_, minor_version_; headers_container_type headers_; string_type body_; source_ = source(request); method_ = method(request); destination_ = destination(request); major_version_ = major_version(request); minor_version_ = minor_version(request); headers_ = headers(request); body_ = body(request); source(request, source_); method(request, method_); destination(request, destination_); major_version(request, major_version_); minor_version(request, minor_version_); headers(request, headers_); add_header(request, string_type(), string_type()); remove_header(request, string_type()); clear_headers(request); body(request, body_); string_type name, value; request << ::boost::network::source(source_) << ::boost::network::destination(destination_) << ::boost::network::http::method(method_) << ::boost::network::http::major_version(major_version_) << ::boost::network::http::minor_version(minor_version_) << ::boost::network::header(name, value) << ::boost::network::body(body_); (void)source_; (void)method_; (void)destination_; (void)major_version_; (void)minor_version_; (void)headers_; (void)body_; (void)name; (void)value; } private: R request; }; template struct ClientRequest : boost::network::Message { typedef typename R::string_type string_type; typedef typename R::port_type port_type; BOOST_CONCEPT_USAGE(ClientRequest) { string_type tmp; R request_(tmp); swap(request, request_); // swappable via ADL string_type host_ = host(request); port_type port_ = port(request); string_type path_ = path(request); string_type query_ = query(request); string_type anchor_ = anchor(request); string_type protocol_ = protocol(request); request << uri(string_type()); boost::network::http::uri(request, string_type()); (void)host_; (void)port_; (void)path_; (void)query_; (void)anchor_; (void)protocol_; } private: R request; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/request_parser.hpp000066400000000000000000000055021256751517300261510ustar00rootroot00000000000000// // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2009 Dean Michael Berris (mikhailberis at gmail dot com) // Copyright (c) 2009 Tarro, Inc. // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Modifications by Dean Michael Berris // #ifndef HTTP_SERVER3_REQUEST_PARSER_HPP #define HTTP_SERVER3_REQUEST_PARSER_HPP #include #include #include namespace boost { namespace network { namespace http { namespace tag { struct default_; } /// Parser for incoming requests. template class basic_request_parser { public: /// Construct ready to parse the request method. basic_request_parser() : state_(method_start) {} /// Reset to initial parser state. void reset() { state_ = method_start; } /// Parse some data. The tribool return value is true when a complete /// request /// has been parsed, false if the data is invalid, indeterminate when /// more /// data is required. The InputIterator return value indicates how much /// of the /// input has been consumed. template boost::tuple parse_headers( basic_request& req, InputIterator begin, InputIterator end) { while (begin != end) { boost::tribool result = consume(req, *begin++); if (result || !result) return boost::make_tuple(result, begin); } boost::tribool result = boost::indeterminate; return boost::make_tuple(result, begin); } private: /// Handle the next character of input. boost::tribool consume(basic_request& req, char input); /// Check if a byte is an HTTP character. static bool is_char(int c); /// Check if a byte is an HTTP control character. static bool is_ctl(int c); /// Check if a byte is defined as an HTTP tspecial character. static bool is_tspecial(int c); /// Check if a byte is a digit. static bool is_digit(int c); /// The current state of the parser. enum state { method_start, method, uri_start, uri, http_version_h, http_version_t_1, http_version_t_2, http_version_p, http_version_slash, http_version_major_start, http_version_major, http_version_minor_start, http_version_minor, expecting_newline_1, header_line_start, header_lws, header_name, space_before_header_value, header_value, expecting_newline_2, expecting_newline_3 } state_; }; } // namespace http } // namespace network } // namespace boost #include #endif // HTTP_SERVER3_REQUEST_PARSER_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/response.hpp000066400000000000000000000061621256751517300247460ustar00rootroot00000000000000// Copyright Dean Michael Berris 2007. // Copyright Michael Dickey 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct basic_response : public message_base::type { typedef typename string::type string_type; private: typedef typename message_base::type base_type; public: typedef Tag tag; basic_response() : base_type() {} basic_response(basic_response const& other) : base_type(other) {} basic_response& operator=(basic_response rhs) { rhs.swap(*this); return *this; }; void swap(basic_response& other) { base_type& base_ref(other), &this_ref(*this); std::swap(this_ref, base_ref); }; }; template inline void swap(basic_response& lhs, basic_response& rhs) { lhs.swap(rhs); } } // namespace http } // namespace network } // namespace boost #include namespace boost { namespace network { namespace http { template basic_response& operator<<(basic_response& message, Directive const& directive) { directive(message); return message; } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/response_concept.hpp000066400000000000000000000036011256751517300264540ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 #define BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct Response : boost::network::Message { typedef typename R::string_type string_type; BOOST_CONCEPT_USAGE(Response) { R response_; swap(response, response_); // swappable via ADL typedef typename traits::version::type version_type; typedef typename traits::status::type status_type; typedef typename traits::status_message::type status_message_type; response << version(version_type()) // version directive << status(status_type()) // status directive << status_message( status_message_type()) // status_message directive ; version(response, version_type()); status(response, status_type()); status_message(response, status_message_type()); string_type version_ = version(response); boost::uint16_t status_ = status(response); string_type status_message_ = status_message(response); (void)version_; (void)status_; (void)status_message_; } private: R response; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 cpp-netlib-0.11.2-final/boost/network/protocol/http/server.hpp000066400000000000000000000037121256751517300244140ustar00rootroot00000000000000// Copyright 2009 (c) Tarro, Inc. // Copyright 2009 (c) Dean Michael Berris // Copyright 2010 (c) Glyn Matthews // Copyright 2003-2008 (c) Chris Kholhoff // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_HTTP_SERVER_HPP_ #define BOOST_NETWORK_HTTP_SERVER_HPP_ #include #include #include #include namespace boost { namespace network { namespace http { template struct server_base { typedef unsupported_tag type; }; template struct server_base >::type> { typedef async_server_base type; }; template struct server_base >::type> { typedef sync_server_base type; }; template struct basic_server : server_base::type {}; template struct server : server_base::type { typedef typename server_base::type server_base; typedef server_options options; explicit server(options const &options) : server_base(options) {} }; template struct async_server : server_base::type { typedef typename server_base::type server_base; typedef server_options options; explicit async_server(options const &options) : server_base(options) {} }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_HTTP_SERVER_HPP_ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/000077500000000000000000000000001256751517300237005ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/server/async_connection.hpp000066400000000000000000000621131256751517300277500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 // Copyright 2010 Dean Michael Berris. // Copyright 2014 Jelle Van den Driessche. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_NETWORK_NO_LIB #include #endif #ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE /** Here we define a page's worth of header connection buffer data. * This can be tuned to reduce the memory cost of connections, but this * default size is set to be friendly to typical service applications. * This is the maximum size though and Boost.Asio's internal representation * of a streambuf would make appropriate decisions on how big a buffer * is to begin with. * * This kinda assumes that a page is by default 4096. Since we're using * the default allocator with the static buffers, it's not guaranteed that * the static buffers will be page-aligned when they are allocated. */ #define BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE 4096 #endif /* BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE */ namespace boost { namespace network { namespace http { #ifndef BOOST_NETWORK_NO_LIB extern void parse_version(std::string const& partial_parsed, fusion::tuple& version_pair); extern void parse_headers(std::string const& input, std::vector& container); #endif template struct async_connection : boost::enable_shared_from_this > { enum status_t { ok = 200, created = 201, accepted = 202, no_content = 204, partial_content = 206, multiple_choices = 300, moved_permanently = 301, moved_temporarily = 302, not_modified = 304, bad_request = 400, unauthorized = 401, forbidden = 403, not_found = 404, not_supported = 405, not_acceptable = 406, request_timeout = 408, precondition_failed = 412, unsatisfiable_range = 416, internal_server_error = 500, not_implemented = 501, bad_gateway = 502, service_unavailable = 503, space_unavailable = 507 }; typedef typename string::type string_type; typedef basic_request request; typedef shared_ptr connection_ptr; private: static char const* status_message(status_t status) { static char const ok_[] = "OK", created_[] = "Created", accepted_[] = "Accepted", no_content_[] = "No Content", multiple_choices_[] = "Multiple Choices", moved_permanently_[] = "Moved Permanently", moved_temporarily_[] = "Moved Temporarily", not_modified_[] = "Not Modified", bad_request_[] = "Bad Request", unauthorized_[] = "Unauthorized", forbidden_[] = "Fobidden", not_found_[] = "Not Found", not_supported_[] = "Not Supported", not_acceptable_[] = "Not Acceptable", internal_server_error_[] = "Internal Server Error", not_implemented_[] = "Not Implemented", bad_gateway_[] = "Bad Gateway", service_unavailable_[] = "Service Unavailable", unknown_[] = "Unknown", partial_content_[] = "Partial Content", request_timeout_[] = "Request Timeout", precondition_failed_[] = "Precondition Failed", unsatisfiable_range_[] = "Requested Range Not Satisfiable", space_unavailable_[] = "Insufficient Space to Store Resource"; switch (status) { case ok: return ok_; case created: return created_; case accepted: return accepted_; case no_content: return no_content_; case multiple_choices: return multiple_choices_; case moved_permanently: return moved_permanently_; case moved_temporarily: return moved_temporarily_; case not_modified: return not_modified_; case bad_request: return bad_request_; case unauthorized: return unauthorized_; case forbidden: return forbidden_; case not_found: return not_found_; case not_supported: return not_supported_; case not_acceptable: return not_acceptable_; case internal_server_error: return internal_server_error_; case not_implemented: return not_implemented_; case bad_gateway: return bad_gateway_; case service_unavailable: return service_unavailable_; case partial_content: return partial_content_; case request_timeout: return request_timeout_; case precondition_failed: return precondition_failed_; case unsatisfiable_range: return unsatisfiable_range_; case space_unavailable: return space_unavailable_; default: return unknown_; } } public: async_connection(asio::io_service& io_service, Handler& handler, utils::thread_pool& thread_pool, boost::shared_ptr ctx = boost::shared_ptr()) : strand(io_service), handler(handler), thread_pool_(thread_pool), headers_buffer( BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE), #ifdef BOOST_NETWORK_ENABLE_HTTPS socket_(io_service, ctx), #else socket_(io_service), #endif handshake_done(false), headers_already_sent(false), headers_in_progress(false) { new_start = read_buffer_.begin(); } ~async_connection() throw() { boost::system::error_code ignored; socket_.shutdown(asio::ip::tcp::socket::shutdown_receive, ignored); } /** Function: template set_headers(Range headers) * Precondition: headers have not been sent yet * Postcondition: headers have been linearized to a buffer, * and assumed to have been sent already when the *function exits * Throws: std::logic_error in case the headers have already been sent. * * A call to set_headers takes a Range where each element models the * Header concept. This Range will be linearized onto a buffer, which *is * then sent as soon as the first call to `write` or `flush` commences. */ template void set_headers(Range headers) { lock_guard lock(headers_mutex); if (headers_in_progress || headers_already_sent) boost::throw_exception( std::logic_error("Headers have already been sent.")); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); typedef constants consts; { std::ostream stream(&headers_buffer); stream << consts::http_slash() << 1 << consts::dot() << 1 << consts::space() << status << consts::space() << status_message(status) << consts::crlf(); if (!boost::empty(headers)) { typedef typename string::type string_type; boost::transform(headers, std::ostream_iterator(stream), linearize_header()); } else { stream << consts::crlf(); } stream << consts::crlf(); } write_headers_only( boost::bind(&async_connection::do_nothing, async_connection::shared_from_this())); } void set_status(status_t new_status) { lock_guard lock(headers_mutex); if (headers_already_sent) boost::throw_exception(std::logic_error( "Headers have already been sent, cannot reset status.")); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); status = new_status; } template void write(Range const& range) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); boost::function f = boost::bind( &async_connection::default_error, async_connection::shared_from_this(), boost::arg<1>()); write_impl(boost::make_iterator_range(range), f); } template typename disable_if< is_base_of, void>::type write(Range const& range, Callback const& callback) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); write_impl(boost::make_iterator_range(range), callback); } template typename enable_if< is_base_of, void>::type write(ConstBufferSeq const& seq, Callback const& callback) { write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); } private: typedef boost::array buffer_type; public: typedef iterator_range input_range; typedef boost::function< void(input_range, boost::system::error_code, std::size_t, connection_ptr)> read_callback_function; void read(read_callback_function callback) { if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); if (new_start != read_buffer_.begin()) { input_range input = boost::make_iterator_range(new_start, read_buffer_.end()); buffer_type::iterator start_tmp = new_start; new_start = read_buffer_.begin(); thread_pool().post( boost::bind(callback, input, boost::system::error_code(), std::distance(start_tmp, data_end), async_connection::shared_from_this())); return; } socket().async_read_some( asio::buffer(read_buffer_), strand.wrap(boost::bind( &async_connection::wrap_read_handler, async_connection::shared_from_this(), callback, asio::placeholders::error, asio::placeholders::bytes_transferred))); } boost::network::stream_handler& socket() { return socket_; } utils::thread_pool& thread_pool() { return thread_pool_; } bool has_error() { return (!!error_encountered); } optional error() { return error_encountered; } private: void wrap_read_handler(read_callback_function callback, boost::system::error_code const& ec, std::size_t bytes_transferred) { if (ec) error_encountered = in_place(ec); buffer_type::const_iterator data_start = read_buffer_.begin(), data_end = read_buffer_.begin(); std::advance(data_end, bytes_transferred); thread_pool().post(boost::bind( callback, boost::make_iterator_range(data_start, data_end), ec, bytes_transferred, async_connection::shared_from_this())); } void default_error(boost::system::error_code const& ec) { error_encountered = in_place(ec); } typedef boost::array array; typedef std::list > array_list; typedef boost::shared_ptr shared_array_list; typedef boost::shared_ptr > shared_buffers; typedef request_parser request_parser_type; typedef boost::lock_guard lock_guard; typedef std::list > pending_actions_list; asio::io_service::strand strand; Handler& handler; utils::thread_pool& thread_pool_; asio::streambuf headers_buffer; boost::network::stream_handler socket_; bool handshake_done; volatile bool headers_already_sent, headers_in_progress; boost::recursive_mutex headers_mutex; buffer_type read_buffer_; status_t status; request_parser_type parser; request request_; buffer_type::iterator new_start, data_end; string_type partial_parsed; optional error_encountered; pending_actions_list pending_actions; template friend struct async_server_base; enum state_t { method, uri, version, headers }; void start() { typename ostringstream::type ip_stream; ip_stream << socket_.remote_endpoint().address().to_v4().to_string() << ':' << socket_.remote_endpoint().port(); request_.source = ip_stream.str(); read_more(method); } void read_more(state_t state) { #ifdef BOOST_NETWORK_ENABLE_HTTPS if (socket_.is_ssl_enabled() && !handshake_done) { socket_.async_handshake( boost::asio::ssl::stream_base::server, boost::bind(&async_connection::handle_handshake, async_connection::shared_from_this(), boost::asio::placeholders::error, state)); } else { #endif socket_.async_read_some( asio::buffer(read_buffer_), strand.wrap( boost::bind(&async_connection::handle_read_data, async_connection::shared_from_this(), state, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); #ifdef BOOST_NETWORK_ENABLE_HTTPS } #endif } void handle_read_data(state_t state, boost::system::error_code const& ec, std::size_t bytes_transferred) { if (!ec) { logic::tribool parsed_ok; iterator_range result_range, input_range; data_end = read_buffer_.begin(); std::advance(data_end, bytes_transferred); switch (state) { case method: input_range = boost::make_iterator_range(new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until(request_parser_type::method_done, input_range); if (!parsed_ok) { client_error(); break; } else if (parsed_ok == true) { swap(partial_parsed, request_.method); request_.method.append(boost::begin(result_range), boost::end(result_range)); trim(request_.method); new_start = boost::end(result_range); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); new_start = read_buffer_.begin(); read_more(method); break; } case uri: input_range = boost::make_iterator_range(new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until(request_parser_type::uri_done, input_range); if (!parsed_ok) { client_error(); break; } else if (parsed_ok == true) { swap(partial_parsed, request_.destination); request_.destination.append(boost::begin(result_range), boost::end(result_range)); trim(request_.destination); new_start = boost::end(result_range); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); new_start = read_buffer_.begin(); read_more(uri); break; } case version: input_range = boost::make_iterator_range(new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::version_done, input_range); if (!parsed_ok) { client_error(); break; } else if (parsed_ok == true) { fusion::tuple version_pair; partial_parsed.append(boost::begin(result_range), boost::end(result_range)); parse_version(partial_parsed, version_pair); request_.http_version_major = fusion::get<0>(version_pair); request_.http_version_minor = fusion::get<1>(version_pair); new_start = boost::end(result_range); partial_parsed.clear(); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); new_start = read_buffer_.begin(); read_more(version); break; } case headers: input_range = boost::make_iterator_range(new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::headers_done, input_range); if (!parsed_ok) { client_error(); break; } else if (parsed_ok == true) { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); try { parse_headers(partial_parsed, request_.headers); } catch (...) { client_error(); break; } new_start = boost::end(result_range); thread_pool().post(boost::bind( &Handler::operator(), &handler, cref(request_), async_connection::shared_from_this())); return; } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); new_start = read_buffer_.begin(); read_more(headers); break; } default: BOOST_ASSERT(false && "This is a bug, report to the cpp-netlib devel " "mailing list!"); std::abort(); } } else { error_encountered = in_place(ec); } } void client_error() { static char const* bad_request = "HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: " "text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; asio::async_write( socket(), asio::buffer(bad_request, strlen(bad_request)), strand.wrap(boost::bind( &async_connection::client_error_sent, async_connection::shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred))); } void client_error_sent(boost::system::error_code const& ec, std::size_t bytes_transferred) { if (!ec) { boost::system::error_code ignored; socket().shutdown(asio::ip::tcp::socket::shutdown_both, ignored); socket().close(ignored); } else { error_encountered = in_place(ec); } } void do_nothing() {} void write_headers_only(boost::function callback) { if (headers_in_progress) return; headers_in_progress = true; asio::async_write( socket(), headers_buffer, strand.wrap(boost::bind( &async_connection::handle_write_headers, async_connection::shared_from_this(), callback, asio::placeholders::error, asio::placeholders::bytes_transferred))); } void handle_write_headers(boost::function callback, boost::system::error_code const& ec, std::size_t bytes_transferred) { lock_guard lock(headers_mutex); if (!ec) { headers_buffer.consume(headers_buffer.size()); headers_already_sent = true; thread_pool().post(callback); pending_actions_list::iterator start = pending_actions.begin(), end = pending_actions.end(); while (start != end) { thread_pool().post(*start++); } pending_actions_list().swap(pending_actions); } else { error_encountered = in_place(ec); } } void handle_write( boost::function callback, shared_array_list temporaries, shared_buffers buffers, boost::system::error_code const& ec, std::size_t bytes_transferred) { // we want to forget the temporaries and buffers thread_pool().post(boost::bind(callback, ec)); } template void write_impl(Range range, boost::function callback) { // linearize the whole range into a vector // of fixed-sized buffers, then schedule an asynchronous // write of these buffers -- make sure they are live // by making these linearized buffers shared and made // part of the completion handler. // // once the range has been linearized and sent, schedule // a wrapper to be called in the io_service's thread, that // will re-schedule the given callback into the thread pool // referred to here so that the io_service's thread can concentrate // on doing I/O. // static std::size_t const connection_buffer_size = BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE; shared_array_list temporaries = boost::make_shared(); shared_buffers buffers = boost::make_shared >(0); std::size_t range_size = boost::distance(range); buffers->reserve((range_size / connection_buffer_size) + ((range_size % connection_buffer_size) ? 1 : 0)); std::size_t slice_size = std::min(range_size, connection_buffer_size); typename boost::range_iterator::type start = boost::begin(range), end = boost::end(range); while (slice_size != 0) { using boost::adaptors::sliced; shared_ptr new_array = make_shared(); boost::copy(range | sliced(0, slice_size), new_array->begin()); temporaries->push_back(new_array); buffers->push_back(asio::buffer(new_array->data(), slice_size)); std::advance(start, slice_size); range = boost::make_iterator_range(start, end); range_size = boost::distance(range); slice_size = std::min(range_size, connection_buffer_size); } if (!buffers->empty()) { write_vec_impl(*buffers, callback, temporaries, buffers); } } template void write_vec_impl(ConstBufferSeq const& seq, Callback const& callback, shared_array_list temporaries, shared_buffers buffers) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); boost::function callback_function = callback; boost::function continuation = boost::bind( &async_connection::template write_vec_impl< ConstBufferSeq, boost::function >, async_connection::shared_from_this(), seq, callback_function, temporaries, buffers); if (!headers_already_sent && !headers_in_progress) { write_headers_only(continuation); return; } else if (headers_in_progress && !headers_already_sent) { pending_actions.push_back(continuation); return; } asio::async_write( socket_, seq, boost::bind(&async_connection::handle_write, async_connection::shared_from_this(), callback_function, temporaries, buffers, asio::placeholders::error, asio::placeholders::bytes_transferred)); } void handle_handshake(const boost::system::error_code& ec, state_t state) { if (!ec) { handshake_done = true; read_more(state); } else { error_encountered = in_place(ec); } } }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/async_server.hpp000066400000000000000000000147351256751517300271260ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 // Copyright 2010 Dean Michael Berris. // Copyright 2014 Jelle Van den Driessche. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct async_server_base : server_storage_base, socket_options_base { typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; typedef typename boost::network::http::response_header::type response_header; typedef async_connection connection; typedef shared_ptr connection_ptr; typedef boost::unique_lock scoped_mutex_lock; explicit async_server_base(server_options const &options) : server_storage_base(options), socket_options_base(options), handler(options.handler()), address_(options.address()), port_(options.port()), thread_pool(options.thread_pool() ? options.thread_pool() : boost::make_shared()), acceptor(server_storage_base::service_), stopping(false), new_connection(), listening_mutex_(), stopping_mutex_(), listening(false), ctx_(options.context()) {} void run() { listen(); service_.run(); }; void stop() { // stop accepting new requests and let all the existing // handlers finish. scoped_mutex_lock listening_lock(listening_mutex_); if (listening) { // we dont bother stopping if we arent currently // listening scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = true; system::error_code ignored; acceptor.close(ignored); listening = false; service_.post(boost::bind(&async_server_base::handle_stop, this)); } } void listen() { scoped_mutex_lock listening_lock(listening_mutex_); BOOST_NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); if (!listening) start_listening(); // we only initialize our acceptor/sockets if we // arent already listening if (!listening) { BOOST_NETWORK_MESSAGE("Error listening on " << address_ << ':' << port_); boost::throw_exception( std::runtime_error("Error listening on provided port.")); } } private: Handler &handler; string_type address_, port_; boost::shared_ptr thread_pool; asio::ip::tcp::acceptor acceptor; bool stopping; connection_ptr new_connection; boost::mutex listening_mutex_; boost::mutex stopping_mutex_; bool listening; boost::shared_ptr ctx_; void handle_stop() { scoped_mutex_lock stopping_lock(stopping_mutex_); if (stopping) service_.stop(); // a user may have started listening again before // the stop command is reached } void handle_accept(boost::system::error_code const &ec) { { scoped_mutex_lock stopping_lock(stopping_mutex_); if (stopping) return; // we dont want to add another handler instance, and we // dont want to know about errors for a socket we dont // need anymore } if (ec) { BOOST_NETWORK_MESSAGE("Error accepting connection, reason: " << ec); } #ifdef BOOST_NETWORK_ENABLE_HTTPS socket_options_base::socket_options(new_connection->socket().next_layer()); #else socket_options_base::socket_options(new_connection->socket()); #endif new_connection->start(); new_connection.reset(new connection(service_, handler, *thread_pool, ctx_)); acceptor.async_accept( #ifdef BOOST_NETWORK_ENABLE_HTTPS new_connection->socket().next_layer(), #else new_connection->socket(), #endif boost::bind(&async_server_base::handle_accept, this, boost::asio::placeholders::error)); } void start_listening() { using boost::asio::ip::tcp; system::error_code error; service_.reset(); // this allows repeated cycles of run -> stop -> // run tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); if (error) { BOOST_NETWORK_MESSAGE("Error resolving '" << address_ << ':' << port_); return; } tcp::endpoint endpoint = *endpoint_iterator; acceptor.open(endpoint.protocol(), error); if (error) { BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ":" << port_); return; } socket_options_base::acceptor_options(acceptor); acceptor.bind(endpoint, error); if (error) { BOOST_NETWORK_MESSAGE("Error binding socket: " << address_ << ":" << port_); return; } acceptor.listen(asio::socket_base::max_connections, error); if (error) { BOOST_NETWORK_MESSAGE("Error listening on socket: '" << error << "' on " << address_ << ":" << port_); return; } new_connection.reset(new connection(service_, handler, *thread_pool, ctx_)); acceptor.async_accept( #ifdef BOOST_NETWORK_ENABLE_HTTPS new_connection->socket().next_layer(), #else new_connection->socket(), #endif boost::bind(&async_server_base::handle_accept, this, boost::asio::placeholders::error)); listening = true; scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = false; // if we were in the process of stopping, we revoke // that command and continue listening BOOST_NETWORK_MESSAGE("Now listening on socket: '" << address_ << ":" << port_ << "'"); } }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/impl/000077500000000000000000000000001256751517300246415ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/server/impl/parsers.ipp000066400000000000000000000043331256751517300270350ustar00rootroot00000000000000#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 #define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 #define BOOST_SPIRIT_UNICODE #include // Copyright 2013 Google, Inc. // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #ifdef BOOST_NETWORK_NO_LIB #ifndef BOOST_NETWORK_INLINE #define BOOST_NETWORK_INLINE inline #endif #else #define BOOST_NETWORK_INLINE #endif #include namespace boost { namespace spirit { namespace traits { typedef std::basic_string u32_string; template <> // struct assign_to_container_from_value { static void call(u32_string const& val, std::string& attr) { u32_to_u8_iterator begin = val.begin(), end = val.end(); for (; begin != end; ++begin) attr += *begin; } }; } // namespace traits } // namespace spirit } // namespace boost namespace boost { namespace network { namespace http { BOOST_NETWORK_INLINE void parse_version( std::string const& partial_parsed, fusion::tuple& version_pair) { using namespace boost::spirit::qi; parse(partial_parsed.begin(), partial_parsed.end(), (lit("HTTP/") >> ushort_ >> '.' >> ushort_), version_pair); } BOOST_NETWORK_INLINE void parse_headers( std::string const& input, std::vector& container) { using namespace boost::spirit::qi; u8_to_u32_iterator begin = input.begin(), end = input.end(); typedef as as_u32_string; parse(begin, end, *(+((alnum | punct) - ':') >> lit(": ") >> as_u32_string()[+((unicode::alnum | space | punct) - '\r' - '\n')] >> lit("\r\n")) >> lit("\r\n"), container); } } // namespace http } // namespace network } // namespace boost #endif /* SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/options.hpp000066400000000000000000000146421256751517300261130ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_20130128 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_20130128 // Copyright 2013 Google, Inc. // Copyright 2013 Dean Michael Berris // Copyright 2014 Jelle Van den Driessche // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct server_options { typedef typename string::type string_type; explicit server_options(Handler &handler) : io_service_(), handler_(handler), address_("localhost"), port_("80"), reuse_address_(false), report_aborted_(false), non_blocking_io_(true), linger_(true), linger_timeout_(0), receive_buffer_size_(), send_buffer_size_(), receive_low_watermark_(), send_low_watermark_(), thread_pool_(), context_() {} server_options(const server_options &other) : io_service_(other.io_service()), handler_(other.handler_), address_(other.address_), port_(other.port_), reuse_address_(other.reuse_address_), report_aborted_(other.report_aborted_), non_blocking_io_(other.non_blocking_io_), linger_(other.linger_), linger_timeout_(0), receive_buffer_size_(other.receive_buffer_size_), send_buffer_size_(other.send_buffer_size_), receive_low_watermark_(other.receive_low_watermark_), send_low_watermark_(other.send_low_watermark_), thread_pool_(other.thread_pool_), context_(other.context_) {} server_options &operator=(server_options other) { other.swap(*this); return *this; } void swap(server_options &other) { using std::swap; swap(io_service_, other.io_service_); swap(address_, other.address_); swap(port_, other.port_); swap(reuse_address_, other.reuse_address_); swap(report_aborted_, other.report_aborted_); swap(non_blocking_io_, other.non_blocking_io_); swap(linger_, other.linger_); swap(linger_timeout_, other.linger_timeout_); swap(receive_buffer_size_, other.receive_buffer_size_); swap(send_buffer_size_, other.send_buffer_size_); swap(receive_low_watermark_, other.receive_low_watermark_); swap(send_low_watermark_, other.send_low_watermark_); swap(thread_pool_, other.thread_pool_); swap(context_, other.context_); } server_options &context(boost::shared_ptr v) { context_ = v; return *this; } server_options &io_service(boost::shared_ptr v) { io_service_ = v; return *this; } server_options &address(string_type const &v) { address_ = v; return *this; } server_options &port(string_type const &v) { port_ = v; return *this; } server_options &reuse_address(bool v) { reuse_address_ = v; return *this; } server_options &report_aborted(bool v) { report_aborted_ = v; return *this; } server_options &non_blocking_io(bool v) { non_blocking_io_ = v; return *this; } server_options &linger(bool v) { linger_ = v; return *this; } server_options &linger_timeout(size_t v) { linger_timeout_ = v; return *this; } server_options &receive_buffer_size( boost::asio::socket_base::receive_buffer_size v) { receive_buffer_size_ = v; return *this; } server_options &send_buffer_size( boost::asio::socket_base::send_buffer_size v) { send_buffer_size_ = v; return *this; } server_options &receive_low_watermark( boost::asio::socket_base::receive_low_watermark v) { receive_low_watermark_ = v; return *this; } server_options &send_low_watermark( boost::asio::socket_base::send_low_watermark v) { send_low_watermark_ = v; return *this; } server_options &thread_pool(boost::shared_ptr v) { thread_pool_ = v; return *this; } boost::shared_ptr io_service() const { return io_service_; } string_type address() const { return address_; } string_type port() const { return port_; } Handler &handler() const { return handler_; } bool reuse_address() const { return reuse_address_; } bool report_aborted() const { return report_aborted_; } bool non_blocking_io() const { return non_blocking_io_; } bool linger() const { return linger_; } size_t linger_timeout() const { return linger_timeout_; } boost::optional receive_buffer_size() const { return receive_buffer_size_; } boost::optional send_buffer_size() const { return send_buffer_size_; } boost::optional receive_low_watermark() const { return receive_low_watermark_; } boost::optional send_low_watermark() const { return send_low_watermark_; } boost::shared_ptr thread_pool() const { return thread_pool_; } boost::shared_ptr context() const { return context_; } private: boost::shared_ptr io_service_; Handler &handler_; string_type address_; string_type port_; bool reuse_address_; bool report_aborted_; bool non_blocking_io_; bool linger_; size_t linger_timeout_; boost::optional receive_buffer_size_; boost::optional send_buffer_size_; boost::optional receive_low_watermark_; boost::optional send_low_watermark_; boost::shared_ptr thread_pool_; boost::shared_ptr context_; }; template inline void swap(server_options &a, server_options &b) { a.swap(b); } } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_20130128 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/request.hpp000066400000000000000000000022331256751517300261010ustar00rootroot00000000000000// // request.hpp // ~~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) // Copyright (c) 2009 Tarro, Inc. // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NETWORK_HTTP_REQUEST_HPP #define BOOST_NETWORK_HTTP_REQUEST_HPP #include #include #include #include "header.hpp" namespace boost { namespace network { namespace http { /// A request received from a client. struct request { std::string method; std::string uri; int http_version_major; int http_version_minor; std::vector
headers; std::string body; }; inline void swap(request& l, request& r) { using std::swap; swap(l.method, r.method); swap(l.uri, r.uri); swap(l.http_version_major, r.http_version_major); swap(l.http_version_minor, r.http_version_minor); swap(l.headers, r.headers); swap(l.body, r.body); } } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_HTTP_REQUEST_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/server/request_parser.hpp000066400000000000000000000152021256751517300274550ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { namespace http { template struct request_parser { enum state_t { method_start, method_char, method_done, uri_char, uri_done, version_h, version_t1, version_t2, version_p, version_slash, version_d1, version_dot, version_d2, version_cr, version_done, header_name, header_colon, header_value, header_cr, header_line_done, headers_cr, headers_done }; explicit request_parser(state_t start_state = method_start) : internal_state(start_state) {} void reset(state_t start_state = method_start) { internal_state = method_start; } state_t state() const { return internal_state; } template fusion::tuple > parse_until(state_t stop_state, Range& range) { logic::tribool parsed_ok = logic::indeterminate; typedef typename range_iterator::type iterator; iterator start = boost::begin(range), end = boost::end(range), current_iterator = start; iterator_range local_range = boost::make_iterator_range(start, end); while (!boost::empty(local_range) && stop_state != internal_state && indeterminate(parsed_ok)) { current_iterator = boost::begin(local_range); switch (internal_state) { case method_start: if (algorithm::is_upper()(*current_iterator)) internal_state = method_char; else parsed_ok = false; break; case method_char: if (algorithm::is_upper()(*current_iterator)) break; else if (algorithm::is_space()(*current_iterator)) internal_state = method_done; else parsed_ok = false; break; case method_done: if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; else if (algorithm::is_space()(*current_iterator)) parsed_ok = false; else internal_state = uri_char; break; case uri_char: if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; else if (algorithm::is_space()(*current_iterator)) internal_state = uri_done; break; case uri_done: if (*current_iterator == 'H') internal_state = version_h; else parsed_ok = false; break; case version_h: if (*current_iterator == 'T') internal_state = version_t1; else parsed_ok = false; break; case version_t1: if (*current_iterator == 'T') internal_state = version_t2; else parsed_ok = false; break; case version_t2: if (*current_iterator == 'P') internal_state = version_p; else parsed_ok = false; break; case version_p: if (*current_iterator == '/') internal_state = version_slash; else parsed_ok = false; break; case version_slash: if (algorithm::is_digit()(*current_iterator)) internal_state = version_d1; else parsed_ok = false; break; case version_d1: if (*current_iterator == '.') internal_state = version_dot; else parsed_ok = false; break; case version_dot: if (algorithm::is_digit()(*current_iterator)) internal_state = version_d2; else parsed_ok = false; break; case version_d2: if (*current_iterator == '\r') internal_state = version_cr; else parsed_ok = false; break; case version_cr: if (*current_iterator == '\n') internal_state = version_done; else parsed_ok = false; break; case version_done: if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name; else if (*current_iterator == '\r') internal_state = headers_cr; else parsed_ok = false; break; case header_name: if (*current_iterator == ':') internal_state = header_colon; else if (algorithm::is_alnum()(*current_iterator) || algorithm::is_punct()(*current_iterator)) break; else parsed_ok = false; break; case header_colon: if (*current_iterator == ' ') internal_state = header_value; else parsed_ok = false; break; case header_value: if (*current_iterator == '\r') internal_state = header_cr; else if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; break; case header_cr: if (*current_iterator == '\n') internal_state = header_line_done; else parsed_ok = false; break; case header_line_done: if (*current_iterator == '\r') internal_state = headers_cr; else if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name; else parsed_ok = false; break; case headers_cr: if (*current_iterator == '\n') internal_state = headers_done; else parsed_ok = false; break; case headers_done: // anything that follows after headers_done is allowed. break; default: parsed_ok = false; }; if (internal_state == stop_state) parsed_ok = true; local_range = boost::make_iterator_range(++current_iterator, end); } return fusion::make_tuple( parsed_ok, boost::make_iterator_range(start, current_iterator)); } private: state_t internal_state; }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/socket_options_base.hpp000066400000000000000000000046111256751517300304500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { struct socket_options_base { protected: asio::socket_base::reuse_address acceptor_reuse_address; asio::socket_base::enable_connection_aborted acceptor_report_aborted; boost::optional receive_buffer_size; boost::optional send_buffer_size; boost::optional receive_low_watermark; boost::optional send_low_watermark; asio::socket_base::non_blocking_io non_blocking_io; asio::socket_base::linger linger; template explicit socket_options_base(server_options const &options) : acceptor_reuse_address(options.reuse_address()), acceptor_report_aborted(options.report_aborted()), receive_buffer_size(options.receive_buffer_size()), send_buffer_size(options.send_buffer_size()), receive_low_watermark(options.receive_low_watermark()), send_low_watermark(options.send_low_watermark()), non_blocking_io(options.non_blocking_io()), linger(options.linger(), options.linger_timeout()) {} void acceptor_options(boost::asio::ip::tcp::acceptor &acceptor) { acceptor.set_option(acceptor_reuse_address); acceptor.set_option(acceptor_report_aborted); } void socket_options(boost::asio::ip::tcp::socket &socket) { boost::system::error_code ignored; socket.io_control(non_blocking_io, ignored); socket.set_option(linger, ignored); if (receive_buffer_size) socket.set_option(*receive_buffer_size, ignored); if (receive_low_watermark) socket.set_option(*receive_low_watermark, ignored); if (send_buffer_size) socket.set_option(*send_buffer_size, ignored); if (send_low_watermark) socket.set_option(*send_low_watermark, ignored); } }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 \ */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/storage_base.hpp000066400000000000000000000021621256751517300270500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { struct server_storage_base { struct no_io_service {}; struct has_io_service {}; protected: template explicit server_storage_base(server_options const& options) : self_service_(options.io_service() ? options.io_service() : boost::make_shared()), service_(*self_service_) {} boost::shared_ptr self_service_; asio::io_service& service_; }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/sync_connection.hpp000066400000000000000000000215551256751517300276140ustar00rootroot00000000000000// Copyright 2009 (c) Dean Michael Berris // Copyright 2009 (c) Tarroo, Inc. // Adapted from Christopher Kholhoff's Boost.Asio Example, released under // the Boost Software License, Version 1.0. (See acccompanying file // LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ #define BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ #ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE #define BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 1024uL #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct sync_connection : boost::enable_shared_from_this > { sync_connection(boost::asio::io_service &service, Handler &handler) : service_(service), handler_(handler), socket_(service_), wrapper_(service_) {} boost::asio::ip::tcp::socket &socket() { return socket_; } void start() { // This is HTTP so we really want to just // read and parse a request that's incoming // and then pass that request object to the // handler_ instance. // using boost::asio::ip::tcp; boost::system::error_code option_error; socket_.set_option(tcp::no_delay(true), option_error); if (option_error) handler_.log(boost::system::system_error(option_error).what()); socket_.async_read_some( boost::asio::buffer(buffer_), wrapper_.wrap( boost::bind(&sync_connection::handle_read_headers, sync_connection::shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } private: struct is_content_length { template bool operator()(Header const &header) { return boost::to_lower_copy(header.name) == "content-length"; } }; void handle_read_headers(boost::system::error_code const &ec, size_t bytes_transferred) { if (!ec) { request_.source = socket_.remote_endpoint().address().to_string(); request_.source_port = socket_.remote_endpoint().port(); boost::tribool done; buffer_type::iterator new_start; tie(done, new_start) = parser_.parse_headers( request_, buffer_.data(), buffer_.data() + bytes_transferred); if (done) { if (request_.method[0] == 'P') { // look for the content-length header typename std::vector::type>::iterator it = std::find_if(request_.headers.begin(), request_.headers.end(), is_content_length()); if (it == request_.headers.end()) { response_ = basic_response::stock_reply( basic_response::bad_request); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap(boost::bind( &sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); return; } size_t content_length = 0; try { content_length = boost::lexical_cast(it->value); } catch (...) { response_ = basic_response::stock_reply( basic_response::bad_request); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap(boost::bind( &sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); return; } if (content_length != 0) { if (new_start != (buffer_.begin() + bytes_transferred)) { request_.body.append(new_start, buffer_.begin() + bytes_transferred); content_length -= std::distance(new_start, buffer_.begin() + bytes_transferred); } if (content_length > 0) { socket_.async_read_some( boost::asio::buffer(buffer_), wrapper_.wrap(boost::bind( &sync_connection::handle_read_body_contents, sync_connection::shared_from_this(), boost::asio::placeholders::error, content_length, boost::asio::placeholders::bytes_transferred))); return; } } handler_(request_, response_); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap( boost::bind(&sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); } else { handler_(request_, response_); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap( boost::bind(&sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); } } else if (!done) { response_ = basic_response::stock_reply(basic_response::bad_request); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap( boost::bind(&sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); } else { socket_.async_read_some( boost::asio::buffer(buffer_), wrapper_.wrap( boost::bind(&sync_connection::handle_read_headers, sync_connection::shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } } // TODO Log the error? } void handle_read_body_contents(boost::system::error_code const &ec, size_t bytes_to_read, size_t bytes_transferred) { if (!ec) { size_t difference = bytes_to_read - bytes_transferred; buffer_type::iterator start = buffer_.begin(), past_end = start; std::advance(past_end, (std::min)(bytes_to_read, bytes_transferred)); request_.body.append(buffer_.begin(), past_end); if (difference == 0) { handler_(request_, response_); boost::asio::async_write( socket_, response_.to_buffers(), wrapper_.wrap( boost::bind(&sync_connection::handle_write, sync_connection::shared_from_this(), boost::asio::placeholders::error))); } else { socket_.async_read_some( boost::asio::buffer(buffer_), wrapper_.wrap(boost::bind( &sync_connection::handle_read_body_contents, sync_connection::shared_from_this(), boost::asio::placeholders::error, difference, boost::asio::placeholders::bytes_transferred))); } } // TODO Log the error? } void handle_write(boost::system::error_code const &ec) { if (!ec) { using boost::asio::ip::tcp; boost::system::error_code ignored_ec; socket_.shutdown(tcp::socket::shutdown_receive, ignored_ec); } } boost::asio::io_service &service_; Handler &handler_; boost::asio::ip::tcp::socket socket_; boost::asio::io_service::strand wrapper_; typedef boost::array buffer_type; buffer_type buffer_; typedef basic_request_parser request_parser; request_parser parser_; basic_request request_; basic_response response_; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ cpp-netlib-0.11.2-final/boost/network/protocol/http/server/sync_server.hpp000066400000000000000000000113141256751517300267530ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Copyright 2010 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 #define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct sync_server_base : server_storage_base, socket_options_base { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; typedef typename boost::network::http::response_header::type response_header; sync_server_base(server_options const& options) : server_storage_base(options), socket_options_base(options), handler_(options.handler()), address_(options.address()), port_(options.port()), acceptor_(server_storage_base::service_), new_connection(), listening_mutex_(), listening_(false) {} void run() { listen(); service_.run(); } void stop() { // stop accepting new connections and let all the existing handlers // finish. system::error_code ignored; acceptor_.close(ignored); service_.stop(); } void listen() { boost::unique_lock listening_lock(listening_mutex_); if (!listening_) start_listening(); } private: Handler& handler_; string_type address_, port_; boost::asio::ip::tcp::acceptor acceptor_; boost::shared_ptr > new_connection; boost::mutex listening_mutex_; bool listening_; void handle_accept(boost::system::error_code const& ec) { if (ec) { } socket_options_base::socket_options(new_connection->socket()); new_connection->start(); new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept( new_connection->socket(), boost::bind(&sync_server_base::handle_accept, this, boost::asio::placeholders::error)); } void start_listening() { using boost::asio::ip::tcp; system::error_code error; tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); if (error) { BOOST_NETWORK_MESSAGE("Error resolving address: " << address_ << ':' << port_); boost::throw_exception(std::runtime_error("Error resolving address.")); } tcp::endpoint endpoint = *endpoint_iterator; acceptor_.open(endpoint.protocol(), error); if (error) { BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); boost::throw_exception(std::runtime_error("Error opening socket.")); } socket_options_base::acceptor_options(acceptor_); acceptor_.bind(endpoint, error); if (error) { BOOST_NETWORK_MESSAGE("Error binding to socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); boost::throw_exception(std::runtime_error("Error binding to socket.")); } acceptor_.listen(tcp::socket::max_connections, error); if (error) { BOOST_NETWORK_MESSAGE("Error listening on socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); boost::throw_exception(std::runtime_error("Error listening on socket.")); } new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept( new_connection->socket(), boost::bind(&sync_server_base::handle_accept, this, boost::asio::placeholders::error)); listening_ = true; } }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/000077500000000000000000000000001256751517300241065ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/support/client_or_server.hpp000066400000000000000000000021001256751517300301540ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 #define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; template struct client_or_server { typedef unsupported_tag type; }; template struct client_or_server >::type> { typedef tags::server type; }; template struct client_or_server >::type> { typedef tags::client type; }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/is_client.hpp000066400000000000000000000014051256751517300265700ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 #define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct is_client : mpl::false_ {}; template struct is_client< Tag, typename enable_if::type> : mpl::true_ {}; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/is_http.hpp000066400000000000000000000014011256751517300262650ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 #define BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct is_http : mpl::false_ {}; template struct is_http::type> : mpl::true_ {}; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/protocol/http/support/is_keepalive.hpp000066400000000000000000000014551256751517300272640ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 #define BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; template struct is_keepalive : mpl::false_ {}; template struct is_keepalive< Tag, typename enable_if::type> : mpl::true_ {}; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/is_server.hpp000066400000000000000000000014051256751517300266200ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 #define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct is_server : mpl::false_ {}; template struct is_server< Tag, typename enable_if::type> : mpl::true_ {}; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/is_simple.hpp000066400000000000000000000013551256751517300266070ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 #define BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct is_simple : mpl::false_ {}; template struct is_simple< Tag, typename enable_if::type> : mpl::true_ {}; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/support/sync_only.hpp000066400000000000000000000017131256751517300266360ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 #define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace http { template struct sync_only : mpl::inherit_linearly< typename mpl::replace_if::type, is_same, tags::sync>::type, mpl::inherit > {}; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/tags.hpp000066400000000000000000000042031256751517300240400ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 #define BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { namespace tags { struct http { typedef mpl::true_::type is_http; }; struct keepalive { typedef mpl::true_::type is_keepalive; }; struct simple { typedef mpl::true_::type is_simple; }; struct server { typedef mpl::true_::type is_server; }; struct client { typedef mpl::true_::type is_client; }; using namespace boost::network::tags; template struct components; typedef mpl::vector http_default_8bit_tcp_resolve_tags; typedef mpl::vector http_default_8bit_udp_resolve_tags; typedef mpl::vector http_keepalive_8bit_tcp_resolve_tags; typedef mpl::vector http_keepalive_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_tcp_resolve_tags; typedef mpl::vector http_server_tags; typedef mpl::vector http_async_server_tags; BOOST_NETWORK_DEFINE_TAG(http_default_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); BOOST_NETWORK_DEFINE_TAG(http_keepalive_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_keepalive_8bit_udp_resolve); BOOST_NETWORK_DEFINE_TAG(http_async_8bit_udp_resolve); BOOST_NETWORK_DEFINE_TAG(http_async_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_server); BOOST_NETWORK_DEFINE_TAG(http_async_server); } /* tags */ } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/traits.hpp000066400000000000000000000014251256751517300244130ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP // Convenience header for including different traits implementations. #include //#include #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/000077500000000000000000000000001256751517300237005ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/connection_keepalive.hpp000066400000000000000000000013341256751517300305760ustar00rootroot00000000000000// Copyright (c) Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 #include #include namespace boost { namespace network { namespace http { template struct connection_keepalive : is_keepalive {}; } /* http */ } /* network */ } /* boost */ #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/connection_policy.hpp000066400000000000000000000041451256751517300301330ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 // Copyright 2013 Google, Inc. // Copyright Dean Michael Berris 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; template struct connection_policy { typedef unsupported_tag type; }; template struct connection_policy >::type> { typedef async_connection_policy type; }; template struct connection_policy< Tag, version_major, version_minor, typename enable_if< mpl::and_, mpl::not_ > > >::type> { typedef simple_connection_policy type; }; template struct connection_policy< Tag, version_major, version_minor, typename enable_if< mpl::and_, mpl::not_ > > >::type> { typedef pooled_connection_policy type; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/delegate_factory.hpp000066400000000000000000000017721256751517300277210ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include namespace boost { namespace network { namespace http { namespace impl { template struct connection_delegate_factory; } /* impl */ template struct unsupported_tag; template struct delegate_factory { typedef unsupported_tag type; }; template struct delegate_factory >::type> { typedef impl::connection_delegate_factory type; }; } /* http */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 */ cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/000077500000000000000000000000001256751517300246415ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/chunk_cache.ipp000066400000000000000000000015531256751517300276120ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP #include #include #include #include namespace boost { namespace network { namespace http { template struct chunk_cache { // TODO define the allocator using an allocator_traits? typedef std::list::type> > type; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/content.ipp000066400000000000000000000022221256751517300270230ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP #include namespace boost { namespace network { namespace http { template <> struct content { static char const* type_html() { static char const* const TYPE_HTML = "text/html"; return TYPE_HTML; }; static char const* type_text() { static char const* const TYPE_TEXT = "text/plain"; return TYPE_TEXT; }; static char const* type_xml() { static char const* const TYPE_XML = "text/xml"; return TYPE_XML; }; static char const* type_urlencoded() { static char const* const TYPE_URLENCODED = "application/x-www-form-urlencoded"; return TYPE_URLENCODED; }; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/cookie_name.ipp000066400000000000000000000012731256751517300276270ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP #include namespace boost { namespace network { namespace http { template <> struct cookie_name { static boost::uint32_t const MAX = 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/cookie_value.ipp000066400000000000000000000013071256751517300300210ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP #include namespace boost { namespace network { namespace http { template <> struct cookie_value { static boost::uint32_t const MAX = 1024u * 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/cookies_container.ipp000066400000000000000000000013721256751517300310540ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP #include #include namespace boost { namespace network { namespace http { template struct cookies_container { typedef std::multimap::type, typename string::type> type; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/delimiters.ipp000066400000000000000000000021551256751517300275170ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP #include namespace boost { namespace network { namespace http { // specialize on the tags::http_default_8bit_tcp_resolve type template <> struct delimiters { static char const* string_crlf() { static char const* const CRLF = "\x0D\x0A"; return CRLF; }; static char const* string_http_version() { static char const* const HTTP_VERSION = "HTTP/1.1"; return HTTP_VERSION; }; static char const* header_name_value_delimiter() { static char const* const HEADER_NAME_VALUE_DELIMITER = ": "; return HEADER_NAME_VALUE_DELIMITER; }; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/header_name.ipp000066400000000000000000000012731256751517300276060ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP #include namespace boost { namespace network { namespace http { template <> struct header_name { static boost::uint32_t const MAX = 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/header_value.ipp000066400000000000000000000013071256751517300300000ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP #include namespace boost { namespace network { namespace http { template <> struct header_value { static boost::uint32_t const MAX = 1024u * 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/headers.ipp000066400000000000000000000041761256751517300267760ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP #include namespace boost { namespace network { namespace http { template <> struct headers_ { static char const* host() { static char const* const HOST = "Host"; return HOST; }; static char const* cookie() { static char const* const COOKIE = "Cookie"; return COOKIE; }; static char const* set_cookie() { static char const* const SET_COOKIE = "Set-Cookie"; return SET_COOKIE; }; static char const* connection() { static char const* const CONNECTION = "Connection"; return CONNECTION; }; static char const* content_type() { static char const* const CONTENT_TYPE = "Content-Type"; return CONTENT_TYPE; }; static char const* content_length() { static char const* const CONTENT_LENGTH = "Content-Length"; return CONTENT_LENGTH; }; static char const* content_location() { static char const* const CONTENT_LOCATION = "Content-Location"; return CONTENT_LOCATION; }; static char const* last_modified() { static char const* const LAST_MODIFIED = "Last-Modified"; return LAST_MODIFIED; }; static char const* if_modified_since() { static char const* const IF_MODIFIED_SINCE = "If-Modified-Since"; return IF_MODIFIED_SINCE; }; static char const* transfer_encoding() { static char const* const TRANSFER_ENCODING = "Transfer-Encoding"; return TRANSFER_ENCODING; }; static char const* location() { static char const* const LOCATION = "Location"; return LOCATION; }; static char const* authorization() { static char const* const AUTHORIZATION = "Authorization"; return AUTHORIZATION; }; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/headers_container.ipp000066400000000000000000000031531256751517300310320ustar00rootroot00000000000000 // Copyright 2013 Google, Inc. // Copyright 2008 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP #include #include #include #include #include #include namespace boost { namespace network { namespace impl { // Moving implementation from original // message_traits implementation by // Atomic Labs, Inc. // -- // returns true if str1 < str2 (ignoring case) struct is_less_ignore_case_impl { inline bool operator()( string::type const& str1, string::type const& str2) const { return to_lower_copy(str1) < to_lower_copy(str2); }; }; template struct headers_container_impl< Tag, typename enable_if::type> { typedef is_less_ignore_case_impl is_less_ignore_case; typedef std::multimap::type, string::type, is_less_ignore_case> type; }; } // namespace impl } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/method.ipp000066400000000000000000000012471256751517300266370ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP #include namespace boost { namespace network { namespace http { template <> struct method { static boost::uint32_t const MAX = 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/post_content.ipp000066400000000000000000000013071256751517300300730ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP #include namespace boost { namespace network { namespace http { template <> struct post_content { static boost::uint32_t const MAX = 1024u * 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/query_container.ipp000066400000000000000000000013621256751517300305640ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP #include #include namespace boost { namespace network { namespace http { template struct query_container { typedef std::multimap::type, typename string::type> type; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/query_name.ipp000066400000000000000000000012671256751517300275260ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP #include namespace boost { namespace network { namespace http { template <> struct query_name { static boost::uint32_t const MAX = 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/query_string.ipp000066400000000000000000000013071256751517300301070ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP #include namespace boost { namespace network { namespace http { template <> struct query_string { static boost::uint32_t const MAX = 1024u * 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/query_value.ipp000066400000000000000000000013031256751517300277110ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP #include namespace boost { namespace network { namespace http { template <> struct query_value { static boost::uint32_t const MAX = 1024u * 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/request_methods.ipp000066400000000000000000000021611256751517300305660ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP #include namespace boost { namespace network { namespace http { template <> struct request_methods { static char const* head() { static char const* const HEAD = "HEAD"; return HEAD; }; static char const* get() { static char const* const GET = "GET"; return GET; }; static char const* put() { static char const* const PUT = "PUT"; return PUT; }; static char const* post() { static char const* const POST = "POST"; return POST; }; static char const* delete_() { static char const* const DELETE_ = "DELETE"; return DELETE_; }; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/resource.ipp000066400000000000000000000012661256751517300272070ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP #include namespace boost { namespace network { namespace http { template <> struct resource { static boost::uint32_t const MAX = 1024u * 256u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/response_code.ipp000066400000000000000000000030541256751517300302050ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP #include #include namespace boost { namespace network { namespace http { /* This glob doesn't have a specialization on the * tags::http_default_8bit_tcp_resolve * yet because it doesn't need to define different behaviour/types * on different message tags -- for example, it doesn't need to * determine the type or change the values of the data no matter * what the tag type is provided. */ template struct response_code { static boost::uint16_t const RC_OK = 200u; static boost::uint16_t const RC_CREATED = 201u; static boost::uint16_t const RC_NO_CONTENT = 204u; static boost::uint16_t const RC_UNAUTHORIZED = 401u; static boost::uint16_t const RC_FORBIDDEN = 403u; static boost::uint16_t const RC_NOT_FOUND = 404u; static boost::uint16_t const RC_METHOD_NOT_ALLOWED = 405u; static boost::uint16_t const RC_NOT_MODIFIED = 304u; static boost::uint16_t const RC_BAD_REQUEST = 400u; static boost::uint16_t const RC_SERVER_ERROR = 500u; static boost::uint16_t const RC_NOT_IMPLEMENTED = 501u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/response_message.ipp000066400000000000000000000040651256751517300307220ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP #include namespace boost { namespace network { namespace http { template <> struct response_message { static char const* ok() { static char const* const RC_OK = "OK"; return RC_OK; }; static char const* created() { static char const* const RC_CREATED = "Created"; return RC_CREATED; }; static char const* no_content() { static char const* const RC_NO_CONTENT = "NO Content"; return RC_NO_CONTENT; }; static char const* unauthorized() { static char const* const RC_UNAUTHORIZED = "Unauthorized"; return RC_UNAUTHORIZED; }; static char const* forbidden() { static char const* const RC_FORBIDDEN = "Fobidden"; return RC_FORBIDDEN; }; static char const* not_found() { static char const* const RC_NOT_FOUND = "Not Found"; return RC_NOT_FOUND; }; static char const* method_not_allowed() { static char const* const RC_METHOD_NOT_ALLOWED = "Method Not Allowed"; return RC_METHOD_NOT_ALLOWED; }; static char const* not_modified() { static char const* const RC_NOT_MODIFIED = "Not Modified"; return RC_NOT_MODIFIED; }; static char const* bad_request() { static char const* const RC_BAD_REQUEST = "Bad Request"; return RC_BAD_REQUEST; }; static char const* server_error() { static char const* const RC_SERVER_ERROR = "Server Error"; return RC_SERVER_ERROR; }; static char const* not_implemented() { static char const* const RC_NOT_IMPLEMENTED = "Not Implemented"; return RC_NOT_IMPLEMENTED; }; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/impl/status_message.ipp000066400000000000000000000013141256751517300304010ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP #include namespace boost { namespace network { namespace http { template <> struct status_message_text { static boost::uint32_t const MAX = 1024u; }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/message_traits.hpp000066400000000000000000000034611256751517300274270ustar00rootroot00000000000000 // This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Some changes Copyright (c) Dean Michael Berris 2008 #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HPP namespace boost { namespace network { namespace http { template struct delimiters; template struct headers_; template struct content; template struct request_methods; template struct response_message; template struct response_code; template struct query_container; template struct cookies_container; template struct chunk_cache; } // namespace http } // namespace network } // namespace boost // Defer definition in implementation files #include #include #include #include #include #include #include #include #include #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/parser_traits.hpp000066400000000000000000000036421256751517300273000ustar00rootroot00000000000000// This file is part of the Boost Network library // Based on the Pion Network Library (r421) // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Some changes Copyright 2008 (c) Dean Michael Berris #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP namespace boost { namespace network { namespace http { template struct status_message_text; template struct method; template struct resource; template struct query_string; template struct header_name; template struct header_value; template struct query_name; template struct query_value; template struct cookie_name; template struct cookie_value; template struct post_content; } // namespace http } // namespace network } // namespace boost // Include implementation files #include #include #include #include #include #include #include #include #include #include #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/resolver.hpp000066400000000000000000000025601256751517300262550ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 // Copyright Dean Michael Berris 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; template struct resolver : mpl::if_, is_http >, boost::asio::ip::tcp::resolver, typename mpl::if_, is_http >, boost::asio::ip::udp::resolver, unsupported_tag >::type> { BOOST_STATIC_ASSERT( (mpl::not_, is_tcp > >::value)); }; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/resolver_policy.hpp000066400000000000000000000022731256751517300276350ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 #define BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 // Copyright Dean Michael Berris 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace http { template struct unsupported_tag; template struct resolver_policy : mpl::if_, is_http >, policies::async_resolver, typename mpl::if_, policies::sync_resolver, unsupported_tag >::type> {}; } // namespace http } // namespace network } // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 cpp-netlib-0.11.2-final/boost/network/protocol/http/traits/vector.hpp000066400000000000000000000014561256751517300257210ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 // Copyright (c) Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template <> struct vector { template struct apply { typedef std::vector type; }; }; template <> struct vector { template struct apply { typedef std::vector type; }; }; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 */ cpp-netlib-0.11.2-final/boost/network/protocol/stream_handler.hpp000066400000000000000000000126721256751517300251240ustar00rootroot00000000000000#ifndef NETLIB_IO_STREAM_HANDLER_HPP #define NETLIB_IO_STREAM_HANDLER_HPP // Copyright 2014 Jelle Van den Driessche. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #ifdef BOOST_NETWORK_ENABLE_HTTPS #include #endif #include #include #include #include #include #include #include #include #include namespace boost { namespace network { typedef boost::asio::ip::tcp::socket tcp_socket; #ifndef BOOST_NETWORK_ENABLE_HTTPS typedef tcp_socket stream_handler; typedef void ssl_context; #else typedef boost::asio::ssl::stream ssl_socket; typedef boost::asio::ssl::context ssl_context; struct stream_handler { public: stream_handler(boost::shared_ptr socket) : tcp_sock_(socket), ssl_enabled(false) {} ~stream_handler() {} stream_handler(boost::shared_ptr socket) : ssl_sock_(socket), ssl_enabled(true) {} stream_handler(boost::asio::io_service& io, boost::shared_ptr ctx = boost::shared_ptr()) { tcp_sock_ = boost::make_shared(boost::ref(io)); ssl_enabled = false; if (ctx) { /// SSL is enabled ssl_sock_ = boost::make_shared(boost::ref(io), boost::ref(*ctx)); ssl_enabled = true; } } template BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(boost::system::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { try { if (ssl_enabled) { ssl_sock_->async_write_some(buffers, handler); } else { tcp_sock_->async_write_some(buffers, handler); } } catch (const boost::system::error_code& e) { std::cerr << e.message() << std::endl; } catch (const boost::system::system_error& e) { std::cerr << e.code() << ": " << e.what() << std::endl; } } template BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(boost::system::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { try { if (ssl_enabled) { ssl_sock_->async_read_some(buffers, handler); } else { tcp_sock_->async_read_some(buffers, handler); } } catch (const boost::system::error_code& e) { std::cerr << e.message() << std::endl; } catch (const boost::system::system_error& e) { std::cerr << e.code() << ": " << e.what() << std::endl; } } void close(boost::system::error_code& e) { if (ssl_enabled) { ssl_sock_->next_layer().close(); } else { tcp_sock_->close(); } } tcp_socket::endpoint_type remote_endpoint() const { if (ssl_enabled) { return ssl_sock_->next_layer().remote_endpoint(); } else { return tcp_sock_->remote_endpoint(); } } void shutdown(boost::asio::socket_base::shutdown_type st, boost::system::error_code& e) { try { if (ssl_enabled) { ssl_sock_->shutdown(e); } else { tcp_sock_->shutdown(boost::asio::ip::tcp::socket::shutdown_send, e); } } catch (const boost::system::error_code& e) { std::cerr << e.message() << std::endl; } catch (const boost::system::system_error& e) { std::cerr << e.code() << ": " << e.what() << std::endl; } } ssl_socket::next_layer_type& next_layer() const { if (ssl_enabled) { return ssl_sock_->next_layer(); } else { return *tcp_sock_; } } ssl_socket::lowest_layer_type& lowest_layer() const { if (ssl_enabled) { return ssl_sock_->lowest_layer(); } else { return tcp_sock_->lowest_layer(); } } template BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code)) async_handshake(ssl_socket::handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) { try { if (ssl_enabled) { return ssl_sock_->async_handshake(type, handler); } else { // NOOP } } catch (const boost::system::error_code& e) { std::cerr << e.message() << std::endl; } catch (const boost::system::system_error& e) { std::cerr << e.code() << ": " << e.what() << std::endl; } } boost::shared_ptr get_tcp_socket() { return tcp_sock_; } boost::shared_ptr get_ssl_socket() { return ssl_sock_; } bool is_ssl_enabled() { return ssl_enabled; } private: boost::shared_ptr tcp_sock_; boost::shared_ptr ssl_sock_; bool ssl_enabled; }; #endif } } #endif cpp-netlib-0.11.2-final/boost/network/support/000077500000000000000000000000001256751517300212665ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/support/is_async.hpp000066400000000000000000000013541256751517300236120ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_20100608 #define BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_20100608 // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_async : mpl::false_ {}; template struct is_async< Tag, typename enable_if::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_2010608 cpp-netlib-0.11.2-final/boost/network/support/is_default_string.hpp000066400000000000000000000013431256751517300255050ustar00rootroot00000000000000// Copyright Dean Michael Berris 2010 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 #define BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 #include #include namespace boost { namespace network { template struct is_default_string : mpl::false_ {}; template struct is_default_string< Tag, typename enable_if::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 cpp-netlib-0.11.2-final/boost/network/support/is_default_wstring.hpp000066400000000000000000000013501256751517300256720ustar00rootroot00000000000000// Copyright Dean Michael Berris 2010 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_SUPPORT_WSTRING_CHECK_20100808 #define BOOST_NETWORK_SUPPORT_WSTRING_CHECK_20100808 #include #include namespace boost { namespace network { template struct is_default_wstring : mpl::false_ {}; template struct is_default_wstring< Tag, typename enable_if::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 cpp-netlib-0.11.2-final/boost/network/support/is_http.hpp000066400000000000000000000013141256751517300234500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 #define BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_http : mpl::false_ {}; template struct is_http::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/support/is_keepalive.hpp000066400000000000000000000013221256751517300244350ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 #define BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_keepalive : mpl::false_ {}; template struct is_keepalive< Tag, typename enable_if::type> : mpl::true_ {}; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/support/is_pod.hpp000066400000000000000000000012641256751517300232570ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 #define BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_pod : mpl::false_ {}; template struct is_pod::type> : mpl::true_ {}; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 */ cpp-netlib-0.11.2-final/boost/network/support/is_simple.hpp000066400000000000000000000013001256751517300237550ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 #define BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_simple : mpl::false_ {}; template struct is_simple< Tag, typename enable_if::type> : mpl::true_ {}; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/support/is_sync.hpp000066400000000000000000000013141256751517300234450ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 #define BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { template struct is_sync : mpl::false_ {}; template struct is_sync::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 cpp-netlib-0.11.2-final/boost/network/support/is_tcp.hpp000066400000000000000000000014041256751517300232570ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 #define BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { template struct is_tcp : mpl::false_ {}; template struct is_tcp::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622cpp-netlib-0.11.2-final/boost/network/support/is_udp.hpp000066400000000000000000000014611256751517300232640ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 #define BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 // Copyright 2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { template struct is_udp : mpl::false_ {}; template struct is_udp::type> : mpl::true_ {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 cpp-netlib-0.11.2-final/boost/network/support/pod_or_normal.hpp000066400000000000000000000014661256751517300246400ustar00rootroot00000000000000#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 #define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace network { template struct pod_or_normal { typedef tags::normal type; }; template struct pod_or_normal< Tag, typename enable_if::type> : tags::pod {}; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 */ cpp-netlib-0.11.2-final/boost/network/support/sync_only.hpp000066400000000000000000000017371256751517300240240ustar00rootroot00000000000000#ifndef BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 #define BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include namespace boost { namespace network { template struct sync_only : mpl::inherit_linearly< typename mpl::replace_if::type, is_same, tags::sync>::type, mpl::inherit > {}; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 */ cpp-netlib-0.11.2-final/boost/network/tags.hpp000066400000000000000000000036371256751517300212320ustar00rootroot00000000000000// Copyright Dean Michael Berris 2008, 2009. // Glyn Matthews 2009 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TAG_INCLUDED_20100808 #define BOOST_NETWORK_TAG_INCLUDED_20100808 #include #include #include #include namespace boost { namespace network { namespace tags { struct pod { typedef mpl::true_::type is_pod; }; struct normal { typedef mpl::true_::type is_normal; }; struct async { typedef mpl::true_::type is_async; }; struct tcp { typedef mpl::true_::type is_tcp; }; struct udp { typedef mpl::true_::type is_udp; }; struct sync { typedef mpl::true_::type is_sync; }; struct default_string { typedef mpl::true_::type is_default_string; }; struct default_wstring { typedef mpl::true_::type is_default_wstring; }; template struct components; // Tag Definition Macro Helper #ifndef BOOST_NETWORK_DEFINE_TAG #define BOOST_NETWORK_DEFINE_TAG(name) \ struct name \ : mpl::inherit_linearly >::type {}; \ template <> \ struct components { \ typedef name##_tags type; \ }; #endif // BOOST_NETWORK_DEFINE_TAG typedef default_string default_; } // namespace tags } // namespace network } // namespace boost #endif // __BOOST_NETWORK_TAGS_INC__ cpp-netlib-0.11.2-final/boost/network/traits/000077500000000000000000000000001256751517300210605ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/traits/char.hpp000066400000000000000000000016401256751517300225070ustar00rootroot00000000000000// Copyright (c) Dean Michael Berris 2008, 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_CHAR_HPP #define BOOST_NETWORK_TRAITS_CHAR_HPP #include #include namespace boost { namespace network { template struct unsupported_tag; template struct char_ { typedef unsupported_tag type; }; template struct char_ >::type> { typedef char type; }; template struct char_ >::type> { typedef wchar_t type; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_CHAR_HPP cpp-netlib-0.11.2-final/boost/network/traits/headers_container.hpp000066400000000000000000000016301256751517300252460ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2009. // Copyright 2013 Google, Inc. // Copyright 2013 Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC #define BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC #include #include #include namespace boost { namespace network { namespace impl { template struct headers_container_impl { typedef std::multimap::type, typename string::type> type; }; } // namespace impl template struct headers_container : impl::headers_container_impl {}; } // namespace network } // namespace boost #endif // __BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC__ cpp-netlib-0.11.2-final/boost/network/traits/istream.hpp000066400000000000000000000017511256751517300232410ustar00rootroot00000000000000 #ifndef BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 #define BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { template struct unsupported_tag; template struct istream { typedef unsupported_tag type; }; template struct istream >::type> { typedef std::istream type; }; template struct istream >::type> { typedef std::wistream type; }; } /* network */ } /* boost */ #endif /* BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 */ cpp-netlib-0.11.2-final/boost/network/traits/istringstream.hpp000066400000000000000000000021271256751517300244660ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2009. // Copyright (c) Dean Michael Berris 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC #define BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC #include #include #include #include namespace boost { namespace network { template struct unsupported_tag; template struct istringstream { typedef unsupported_tag type; }; template struct istringstream >::type> { typedef std::istringstream type; }; template struct istringstream >::type> { typedef std::basic_istringstream type; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC cpp-netlib-0.11.2-final/boost/network/traits/ostream_iterator.hpp000066400000000000000000000020501256751517300251510ustar00rootroot00000000000000#ifndef BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 #define BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 // Copyright 2010 (C) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include namespace boost { namespace network { template struct unsupported_tag; template struct ostream_iterator; template struct ostream_iterator : mpl::if_, std::ostream_iterator, typename mpl::if_, std::ostream_iterator, unsupported_tag >::type> {}; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 cpp-netlib-0.11.2-final/boost/network/traits/ostringstream.hpp000066400000000000000000000021531256751517300244730ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2009. // Copyright (c) Dean Michael Berris 2009, 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC #define BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC #include #include #include #include #include namespace boost { namespace network { template struct unsupported_tag; template struct ostringstream { typedef unsupported_tag type; }; template struct ostringstream >::type> { typedef std::ostringstream type; }; template struct ostringstream >::type> { typedef std::wostringstream type; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC cpp-netlib-0.11.2-final/boost/network/traits/string.hpp000066400000000000000000000023721256751517300231030ustar00rootroot00000000000000// Copyright (c) Dean Michael Berris 2008, 2009. // Glyn Matthews 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_STRING_INC #define BOOST_NETWORK_TRAITS_STRING_INC #include #include #include #include #ifndef BOOST_NETWORK_DEFAULT_STRING #define BOOST_NETWORK_DEFAULT_STRING std::string #endif #ifndef BOOST_NETWORK_DEFAULT_WSTRING #define BOOST_NETWORK_DEFAULT_WSTRING std::wstring #endif namespace boost { namespace network { template struct unsupported_tag; template struct string { typedef unsupported_tag type; }; template struct string >::type> { typedef BOOST_NETWORK_DEFAULT_STRING type; }; template struct string >::type> { typedef BOOST_NETWORK_DEFAULT_WSTRING type; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_STRING_INC cpp-netlib-0.11.2-final/boost/network/traits/vector.hpp000066400000000000000000000013541256751517300230760ustar00rootroot00000000000000// Copyright (c) Dean Michael Berris 2008, 2009. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_TRAITS_VECTOR_HPP #define BOOST_NETWORK_TRAITS_VECTOR_HPP #include #include namespace boost { namespace network { template struct unsupported_tag; template struct vector { template struct apply : mpl::if_, std::vector, unsupported_tag > {}; }; } // namespace network } // namespace boost #endif // BOOST_NETWORK_TRAITS_VECTOR_HPP cpp-netlib-0.11.2-final/boost/network/uri.hpp000066400000000000000000000004601256751517300210620ustar00rootroot00000000000000#ifndef BOOST_NETWORK_URL_HPP_ #define BOOST_NETWORK_URL_HPP_ // Copyright 2009 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #endif cpp-netlib-0.11.2-final/boost/network/uri/000077500000000000000000000000001256751517300203515ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/uri/accessors.hpp000066400000000000000000000060171256751517300230530ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ #define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ #include #include #include #include #include namespace boost { namespace network { namespace uri { namespace details { template struct key_value_sequence : spirit::qi::grammar { typedef typename Map::key_type key_type; typedef typename Map::mapped_type mapped_type; typedef std::pair pair_type; key_value_sequence() : key_value_sequence::base_type(query) { query = pair >> *((spirit::qi::lit(';') | '&') >> pair); pair = key >> -('=' >> value); key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("-+.~a-zA-Z_0-9/%"); value = *spirit::qi::char_("-+.~a-zA-Z_0-9/%"); } spirit::qi::rule query; spirit::qi::rule pair; spirit::qi::rule key; spirit::qi::rule value; }; } // namespace details template inline Map &query_map(const uri &uri_, Map &map) { const uri::string_type range = uri_.query(); details::key_value_sequence parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } inline uri::string_type username(const uri &uri_) { const uri::string_type user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { break; } } return uri::string_type(boost::begin(user_info), it); } inline uri::string_type password(const uri &uri_) { const uri::string_type user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } return uri::string_type(it, boost::end(user_info)); } inline uri::string_type decoded_path(const uri &uri_) { const uri::string_type path = uri_.path(); uri::string_type decoded_path; decode(path, std::back_inserter(decoded_path)); return decoded_path; } inline uri::string_type decoded_query(const uri &uri_) { const uri::string_type query = uri_.query(); uri::string_type decoded_query; decode(query, std::back_inserter(decoded_query)); return decoded_query; } inline uri::string_type decoded_fragment(const uri &uri_) { const uri::string_type fragment = uri_.fragment(); uri::string_type decoded_fragment; decode(fragment, std::back_inserter(decoded_fragment)); return decoded_fragment; } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ cpp-netlib-0.11.2-final/boost/network/uri/builder.hpp000066400000000000000000000071521256751517300225150ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_BUILDER_INC__ #define __BOOST_NETWORK_URI_BUILDER_INC__ #include #include namespace boost { namespace network { namespace uri { class builder { typedef uri::string_type string_type; public: builder(uri &uri_) : uri_(uri_) {} builder &set_scheme(const string_type &scheme) { uri_.uri_.append(scheme); if (opaque_schemes::exists(scheme)) { uri_.uri_.append(":"); } else { uri_.uri_.append("://"); } uri_.parse(); return *this; } builder &scheme(const string_type &scheme) { return set_scheme(scheme); } builder &set_user_info(const string_type &user_info) { uri_.uri_.append(user_info); uri_.uri_.append("@"); uri_.parse(); return *this; } builder &user_info(const string_type &user_info) { return set_user_info(user_info); } builder &set_host(const string_type &host) { uri_.uri_.append(host); uri_.parse(); return *this; } builder &host(const string_type &host) { return set_host(host); } builder &set_host(const asio::ip::address &address) { uri_.uri_.append(address.to_string()); uri_.parse(); return *this; } builder &host(const asio::ip::address &host) { return set_host(host); } builder &set_host(const asio::ip::address_v4 &address) { uri_.uri_.append(address.to_string()); uri_.parse(); return *this; } builder &host(const asio::ip::address_v4 &host) { return set_host(host); } builder &set_host(const asio::ip::address_v6 &address) { uri_.uri_.append("["); uri_.uri_.append(address.to_string()); uri_.uri_.append("]"); uri_.parse(); return *this; } builder &host(const asio::ip::address_v6 &host) { return set_host(host); } builder &set_port(const string_type &port) { uri_.uri_.append(":"); uri_.uri_.append(port); uri_.parse(); return *this; } builder &port(const string_type &port) { return set_port(port); } builder &port(uint16_t port) { return set_port(boost::lexical_cast(port)); } builder &set_path(const string_type &path) { uri_.uri_.append(path); uri_.parse(); return *this; } builder &path(const string_type &path) { return set_path(path); } builder &encoded_path(const string_type &path) { string_type encoded_path; encode(path, std::back_inserter(encoded_path)); return set_path(encoded_path); } builder &set_query(const string_type &query) { uri_.uri_.append("?"); uri_.uri_.append(query); uri_.parse(); return *this; } builder &set_query(const string_type &key, const string_type &value) { if (!uri_.query_range()) { uri_.uri_.append("?"); } else { uri_.uri_.append("&"); } uri_.uri_.append(key); uri_.uri_.append("="); uri_.uri_.append(value); uri_.parse(); return *this; } builder &query(const string_type &query) { return set_query(query); } builder &query(const string_type &key, const string_type &value) { return set_query(key, value); } builder &set_fragment(const string_type &fragment) { uri_.uri_.append("#"); uri_.uri_.append(fragment); uri_.parse(); return *this; } builder &fragment(const string_type &fragment) { return set_fragment(fragment); } private: uri &uri_; }; } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_BUILDER_INC__ cpp-netlib-0.11.2-final/boost/network/uri/config.hpp000066400000000000000000000011261256751517300223270ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_CONFIG_INC__ #define __BOOST_NETWORK_URI_CONFIG_INC__ #include #include #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URI_DYN_LINK) #define BOOST_URI_DECL #else #define BOOST_URI_DECL #endif // defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URI_DYN_LINK) #endif // __BOOST_NETWORK_URI_CONFIG_INC__ cpp-netlib-0.11.2-final/boost/network/uri/decode.hpp000066400000000000000000000042231256751517300223060ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DECODE_INC__ #define __BOOST_NETWORK_URI_DECODE_INC__ #include #include #include #include namespace boost { namespace network { namespace uri { namespace detail { template CharT letter_to_hex(CharT in) { switch (in) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return in - '0'; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return in + 10 - 'a'; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return in + 10 - 'A'; } return CharT(); } } // namespace detail template OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { typedef typename boost::iterator_value::type value_type; InputIterator it = in_begin; OutputIterator out = out_begin; while (it != in_end) { if (*it == '%') { ++it; value_type v0 = detail::letter_to_hex(*it); ++it; value_type v1 = detail::letter_to_hex(*it); ++it; *out++ = 0x10 * v0 + v1; } else if (*it == '+') { *out++ = ' '; ++it; } else { *out++ = *it++; } } return out; } template inline OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { return decode(boost::begin(range), boost::end(range), out); } inline std::string decoded(const std::string &input) { std::string decoded; decode(input, std::back_inserter(decoded)); return decoded; } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DECODE_INC__ cpp-netlib-0.11.2-final/boost/network/uri/detail/000077500000000000000000000000001256751517300216135ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/uri/detail/uri_parts.hpp000066400000000000000000000047351256751517300243450ustar00rootroot00000000000000// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn // Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ #define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ #include #include namespace boost { namespace network { namespace uri { namespace detail { template struct hierarchical_part { optional > user_info; optional > host; optional > port; optional > path; FwdIter begin() const { return boost::begin(user_info); } FwdIter end() const { return boost::end(path); } void update() { if (!user_info) { if (host) { user_info = iterator_range(boost::begin(host.get()), boost::begin(host.get())); } else if (path) { user_info = iterator_range(boost::begin(path.get()), boost::begin(path.get())); } } if (!host) { host = iterator_range(boost::begin(path.get()), boost::begin(path.get())); } if (!port) { port = iterator_range(boost::end(host.get()), boost::end(host.get())); } if (!path) { path = iterator_range(boost::end(port.get()), boost::end(port.get())); } } }; template struct uri_parts { iterator_range scheme; hierarchical_part hier_part; optional > query; optional > fragment; FwdIter begin() const { return boost::begin(scheme); } FwdIter end() const { return boost::end(fragment); } void update() { hier_part.update(); if (!query) { query = iterator_range(boost::end(hier_part.path.get()), boost::end(hier_part.path.get())); } if (!fragment) { fragment = iterator_range(boost::end(query.get()), boost::end(query.get())); } } }; } // namespace detail } // namespace uri } // namespace network } // namespace boost #endif // BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ cpp-netlib-0.11.2-final/boost/network/uri/directives.hpp000066400000000000000000000023301256751517300232210ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_INC__ #include namespace boost { namespace network { namespace uri { inline uri &operator<<(uri &uri_, const uri &root_uri) { if (empty(uri_) && valid(root_uri)) { uri_.append(boost::begin(root_uri), boost::end(root_uri)); } return uri_; } template inline uri &operator<<(uri &uri_, const Directive &directive) { directive(uri_); return uri_; } } // namespace uri } // namespace network } // namespace boost #include #include #include #include #include #include #include #include #endif // __BOOST_NETWORK_URI_DIRECTIVES_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/000077500000000000000000000000001256751517300225125ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/uri/directives/authority.hpp000066400000000000000000000015451256751517300252600ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ namespace boost { namespace network { namespace uri { struct authority_directive { explicit authority_directive(const std::string &authority) : authority(authority) {} template void operator()(Uri &uri) const { uri.append(authority); } std::string authority; }; inline authority_directive authority(const std::string &authority) { return authority_directive(authority); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/fragment.hpp000066400000000000000000000017241256751517300250320ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ #include #include #include namespace boost { namespace network { namespace uri { struct fragment_directive { explicit fragment_directive(const std::string &fragment) : fragment(fragment) {} template void operator()(Uri &uri) const { uri.append("#"); uri.append(fragment); } std::string fragment; }; inline fragment_directive fragment(const std::string &fragment) { return fragment_directive(fragment); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/host.hpp000066400000000000000000000015251256751517300242030ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ #include #include namespace boost { namespace network { namespace uri { struct host_directive { explicit host_directive(const std::string &host) : host(host) {} template void operator()(Uri &uri) const { uri.append(host); } std::string host; }; inline host_directive host(const std::string &host) { return host_directive(host); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/path.hpp000066400000000000000000000023631256751517300241630ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ #include #include namespace boost { namespace network { namespace uri { struct path_directive { explicit path_directive(const std::string &path) : path(path) {} template void operator()(Uri &uri) const { uri.append(path); } std::string path; }; struct encoded_path_directive { explicit encoded_path_directive(const std::string &path) : path(path) {} void operator()(uri &uri_) const { std::string encoded_path; encode(path, std::back_inserter(encoded_path)); uri_.append(encoded_path); } std::string path; }; inline path_directive path(const std::string &path) { return path_directive(path); } inline encoded_path_directive encoded_path(const std::string &path) { return encoded_path_directive(path); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/port.hpp000066400000000000000000000021471256751517300242130ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ #include #include #include #include namespace boost { namespace network { namespace uri { struct port_directive { explicit port_directive(const std::string &port) : port(port) {} explicit port_directive(boost::uint16_t port) : port(boost::lexical_cast(port)) {} template void operator()(Uri &uri) const { uri.append(":"); uri.append(port); } std::string port; }; inline port_directive port(const std::string &port) { return port_directive(port); } inline port_directive port(boost::uint16_t port) { return port_directive(port); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/query.hpp000066400000000000000000000030521256751517300243700ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ #include #include #include namespace boost { namespace network { namespace uri { struct query_directive { explicit query_directive(const std::string &query) : query(query) {} template void operator()(Uri &uri) const { uri.append("?"); uri.append(query); } std::string query; }; inline query_directive query(const std::string &query) { return query_directive(query); } struct query_key_query_directive { query_key_query_directive(const std::string &key, const std::string &query) : key(key), query(query) {} template void operator()(Uri &uri) const { std::string encoded_key, encoded_query; if (boost::empty(uri.query())) { uri.append("?"); } else { uri.append("&"); } uri.append(key); uri.append("="); uri.append(query); } std::string key; std::string query; }; inline query_key_query_directive query(const std::string &key, const std::string &query) { return query_key_query_directive(key, query); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/scheme.hpp000066400000000000000000000023671256751517300244770ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ #include #include #include namespace boost { namespace network { namespace uri { struct scheme_directive { explicit scheme_directive(const std::string &scheme) : scheme(scheme) {} template void operator()(Uri &uri) const { uri.append(scheme); if (opaque_schemes::exists(scheme)) { uri.append(":"); } else { uri.append("://"); } } std::string scheme; }; inline scheme_directive scheme(const std::string &scheme) { return scheme_directive(scheme); } namespace schemes { inline uri &http(uri &uri_) { return uri_ << scheme("http"); } inline uri &https(uri &uri_) { return uri_ << scheme("https"); } inline uri &file(uri &uri_) { return uri_ << scheme("file"); } } // namespace schemes } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ cpp-netlib-0.11.2-final/boost/network/uri/directives/user_info.hpp000066400000000000000000000016731256751517300252230ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ #define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ #include #include namespace boost { namespace network { namespace uri { struct user_info_directive { explicit user_info_directive(const std::string &user_info) : user_info(user_info) {} template void operator()(Uri &uri) const { uri.append(user_info); uri.append("@"); } std::string user_info; }; inline user_info_directive user_info(const std::string &user_info) { return user_info_directive(user_info); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ cpp-netlib-0.11.2-final/boost/network/uri/encode.hpp000066400000000000000000000057011256751517300223220ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_ENCODE_INC__ #define __BOOST_NETWORK_URI_ENCODE_INC__ #include #include #include #include #include namespace boost { namespace network { namespace uri { namespace detail { template inline CharT hex_to_letter(CharT in) { switch (in) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: return in + '0'; case 10: case 11: case 12: case 13: case 14: default: return in - 10 + 'A'; } return CharT(); } template void encode_char(CharT in, OutputIterator &out) { switch (in) { case 'a': case 'A': case 'b': case 'B': case 'c': case 'C': case 'd': case 'D': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'h': case 'H': case 'i': case 'I': case 'j': case 'J': case 'k': case 'K': case 'l': case 'L': case 'm': case 'M': case 'n': case 'N': case 'o': case 'O': case 'p': case 'P': case 'q': case 'Q': case 'r': case 'R': case 's': case 'S': case 't': case 'T': case 'u': case 'U': case 'v': case 'V': case 'w': case 'W': case 'x': case 'X': case 'y': case 'Y': case 'z': case 'Z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '.': case '_': case '~': case '/': out++ = in; break; default: out++ = '%'; out++ = hex_to_letter((in >> 4) & 0x0f); out++ = hex_to_letter(in & 0x0f); ; } } } // namespace detail template OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { InputIterator it = in_begin; OutputIterator out = out_begin; while (it != in_end) { detail::encode_char(*it, out); ++it; } return out; } template inline OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { return encode(boost::begin(range), boost::end(range), out); } inline std::string encoded(const std::string &input) { std::string encoded; encode(input, std::back_inserter(encoded)); return encoded; } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_ENCODE_INC__ cpp-netlib-0.11.2-final/boost/network/uri/schemes.hpp000066400000000000000000000012261256751517300225120ustar00rootroot00000000000000// Copyright 2012 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_SCHEMES_INC__ #define __BOOST_NETWORK_URI_SCHEMES_INC__ #include namespace boost { namespace network { namespace uri { class hierarchical_schemes { public: static bool exists(const std::string &scheme); }; class opaque_schemes { public: static bool exists(const std::string &scheme); }; } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_SCHEMES_INC__ cpp-netlib-0.11.2-final/boost/network/uri/uri.hpp000066400000000000000000000246341256751517300216720ustar00rootroot00000000000000// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn // Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_INC__ #define __BOOST_NETWORK_URI_INC__ #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace uri { namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, uri_parts &parts); } // namespace detail class BOOST_URI_DECL uri { friend class builder; public: typedef std::string string_type; typedef string_type::value_type value_type; typedef string_type::const_iterator const_iterator; typedef boost::iterator_range const_range_type; uri() : is_valid_(false) {} // uri(const value_type *uri) // : uri_(uri), is_valid_(false) { // parse(); //} uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); } template uri(const FwdIter &first, const FwdIter &last) : uri_(first, last), is_valid_(false) { parse(); } uri(const uri &other) : uri_(other.uri_) { parse(); } uri &operator=(const uri &other) { uri(other).swap(*this); return *this; } uri &operator=(const string_type &uri_string) { uri(uri_string).swap(*this); return *this; } ~uri() {} void swap(uri &other) { boost::swap(uri_, other.uri_); other.parse(); boost::swap(is_valid_, other.is_valid_); } const_iterator begin() const { return uri_.begin(); } const_iterator end() const { return uri_.end(); } const_range_type scheme_range() const { return uri_parts_.scheme; } const_range_type user_info_range() const { return uri_parts_.hier_part.user_info ? uri_parts_.hier_part.user_info.get() : const_range_type(); } const_range_type host_range() const { return uri_parts_.hier_part.host ? uri_parts_.hier_part.host.get() : const_range_type(); } const_range_type port_range() const { return uri_parts_.hier_part.port ? uri_parts_.hier_part.port.get() : const_range_type(); } const_range_type path_range() const { return uri_parts_.hier_part.path ? uri_parts_.hier_part.path.get() : const_range_type(); } const_range_type query_range() const { return uri_parts_.query ? uri_parts_.query.get() : const_range_type(); } const_range_type fragment_range() const { return uri_parts_.fragment ? uri_parts_.fragment.get() : const_range_type(); } string_type scheme() const { const_range_type range = scheme_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type user_info() const { const_range_type range = user_info_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type host() const { const_range_type range = host_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type port() const { const_range_type range = port_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type path() const { const_range_type range = path_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type query() const { const_range_type range = query_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type fragment() const { const_range_type range = fragment_range(); return range ? string_type(boost::begin(range), boost::end(range)) : string_type(); } string_type string() const { return uri_; } bool is_valid() const { return is_valid_; } void append(const string_type &data) { uri_.append(data); parse(); } template void append(const FwdIter &first, const FwdIter &last) { uri_.append(first, last); parse(); } private: void parse(); string_type uri_; detail::uri_parts uri_parts_; bool is_valid_; }; inline void uri::parse() { const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); if (is_valid_) { if (!uri_parts_.scheme) { uri_parts_.scheme = const_range_type(boost::begin(uri_), boost::begin(uri_)); } uri_parts_.update(); } } inline uri::string_type scheme(const uri &uri_) { return uri_.scheme(); } inline uri::string_type user_info(const uri &uri_) { return uri_.user_info(); } inline uri::string_type host(const uri &uri_) { return uri_.host(); } inline uri::string_type port(const uri &uri_) { return uri_.port(); } inline boost::optional port_us(const uri &uri_) { uri::string_type port = uri_.port(); return (port.empty()) ? boost::optional() : boost::optional( boost::lexical_cast(port)); } inline uri::string_type path(const uri &uri_) { return uri_.path(); } inline uri::string_type query(const uri &uri_) { return uri_.query(); } inline uri::string_type fragment(const uri &uri_) { return uri_.fragment(); } inline uri::string_type hierarchical_part(const uri &uri_) { uri::string_type::const_iterator first, last; uri::const_range_type user_info = uri_.user_info_range(); uri::const_range_type host = uri_.host_range(); uri::const_range_type port = uri_.port_range(); uri::const_range_type path = uri_.path_range(); if (user_info) { first = boost::begin(user_info); } else { first = boost::begin(host); } if (path) { last = boost::end(path); } else if (port) { last = boost::end(port); } else { last = boost::end(host); } return uri::string_type(first, last); } inline uri::string_type authority(const uri &uri_) { uri::string_type::const_iterator first, last; uri::const_range_type user_info = uri_.user_info_range(); uri::const_range_type host = uri_.host_range(); uri::const_range_type port = uri_.port_range(); if (user_info) { first = boost::begin(user_info); } else { first = boost::begin(host); } if (port) { last = boost::end(port); } else { last = boost::end(host); } return uri::string_type(first, last); } inline bool valid(const uri &uri_) { return uri_.is_valid(); } inline bool is_absolute(const uri &uri_) { return uri_.is_valid() && !boost::empty(uri_.scheme_range()); } inline bool is_relative(const uri &uri_) { return uri_.is_valid() && boost::empty(uri_.scheme_range()); } inline bool is_hierarchical(const uri &uri_) { return is_absolute(uri_) && hierarchical_schemes::exists(scheme(uri_)); } inline bool is_opaque(const uri &uri_) { return is_absolute(uri_) && opaque_schemes::exists(scheme(uri_)); } inline bool is_valid(const uri &uri_) { return valid(uri_); } inline void swap(uri &lhs, uri &rhs) { lhs.swap(rhs); } inline std::size_t hash_value(const uri &uri_) { std::size_t seed = 0; for (uri::const_iterator it = begin(uri_); it != end(uri_); ++it) { hash_combine(seed, *it); } return seed; } inline bool operator==(const uri &lhs, const uri &rhs) { return boost::equal(lhs, rhs); } inline bool operator==(const uri &lhs, const uri::string_type &rhs) { return boost::equal(lhs, rhs); } inline bool operator==(const uri::string_type &lhs, const uri &rhs) { return boost::equal(lhs, rhs); } inline bool operator==(const uri &lhs, const uri::value_type *rhs) { return boost::equal(lhs, boost::as_literal(rhs)); } inline bool operator==(const uri::value_type *lhs, const uri &rhs) { return boost::equal(boost::as_literal(lhs), rhs); } inline bool operator!=(const uri &lhs, const uri &rhs) { return !(lhs == rhs); } inline bool operator<(const uri &lhs, const uri &rhs) { return lhs.string() < rhs.string(); } } // namespace uri } // namespace network } // namespace boost #include #include #include namespace boost { namespace network { namespace uri { inline uri from_parts(const uri &base_uri, const uri::string_type &path_, const uri::string_type &query_, const uri::string_type &fragment_) { uri uri_(base_uri); builder(uri_).path(path_).query(query_).fragment(fragment_); return uri_; } inline uri from_parts(const uri &base_uri, const uri::string_type &path_, const uri::string_type &query_) { uri uri_(base_uri); builder(uri_).path(path_).query(query_); return uri_; } inline uri from_parts(const uri &base_uri, const uri::string_type &path_) { uri uri_(base_uri); builder(uri_).path(path_); return uri_; } inline uri from_parts(const uri::string_type &base_uri, const uri::string_type &path, const uri::string_type &query, const uri::string_type &fragment) { return from_parts(uri(base_uri), path, query, fragment); } inline uri from_parts(const uri::string_type &base_uri, const uri::string_type &path, const uri::string_type &query) { return from_parts(uri(base_uri), path, query); } inline uri from_parts(const uri::string_type &base_uri, const uri::string_type &path) { return from_parts(uri(base_uri), path); } } // namespace uri } // namespace network } // namespace boost #include namespace boost { namespace network { namespace uri { inline uri from_file(const filesystem::path &path_) { uri uri_; builder(uri_).scheme("file").path(path_.string()); return uri_; } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_INC__ cpp-netlib-0.11.2-final/boost/network/uri/uri.ipp000066400000000000000000000210161256751517300216620ustar00rootroot00000000000000// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn // Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include BOOST_FUSION_ADAPT_TPL_STRUCT( (FwdIter), (boost::network::uri::detail::hierarchical_part)(FwdIter), (boost::optional >, user_info)(boost::optional >, host)(boost::optional >, port)(boost::optional >, path)); BOOST_FUSION_ADAPT_TPL_STRUCT( (FwdIter), (boost::network::uri::detail::uri_parts)(FwdIter), (boost::iterator_range, scheme)(boost::network::uri::detail::hierarchical_part, hier_part)(boost::optional >, query)(boost::optional >, fragment)); namespace boost { namespace network { namespace uri { namespace detail { namespace qi = boost::spirit::qi; template struct uri_grammar : qi::grammar()> { typedef String string_type; typedef typename String::const_iterator const_iterator; uri_grammar() : uri_grammar::base_type(start, "uri") { // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" gen_delims %= qi::char_(":/?#[]@"); // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," // / ";" / "=" sub_delims %= qi::char_("!$&'()*+,;="); // reserved = gen-delims / sub-delims reserved %= gen_delims | sub_delims; // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" unreserved %= qi::alnum | qi::char_("-._~"); // pct-encoded = "%" HEXDIG HEXDIG pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" pchar %= qi::raw[unreserved | pct_encoded | sub_delims | qi::char_(":@")]; // segment = *pchar segment %= qi::raw[*pchar]; // segment-nz = 1*pchar segment_nz %= qi::raw[+pchar]; // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) segment_nz_nc %= qi::raw[+(unreserved | pct_encoded | sub_delims | qi::char_("@"))]; // path-abempty = *( "/" segment ) path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; // path-absolute = "/" [ segment-nz *( "/" segment ) ] path_absolute %= qi::raw [qi::char_("/") >> -(segment_nz >> *(qi::char_("/") >> segment))]; // path-rootless = segment-nz *( "/" segment ) path_rootless %= qi::raw[segment_nz >> *(qi::char_("/") >> segment)]; // path-empty = 0 path_empty %= qi::raw[qi::eps]; // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) scheme %= qi::raw[qi::alpha >> *(qi::alnum | qi::char_("+.-"))]; // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) user_info %= qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]; ip_literal %= qi::lit('[') >> (ipv6address | ipvfuture) >> ']'; ipvfuture %= qi::lit('v') >> +qi::xdigit >> '.' >> +(unreserved | sub_delims | ':'); ipv6address %= qi::raw [qi::repeat(6)[h16 >> ':'] >> ls32 | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 | -qi::raw[h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 | -qi::raw[h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 | -qi::raw[h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 | -qi::raw[h16] >> "::" >> h16 >> ':' >> ls32 | -qi::raw[h16] >> "::" >> ls32 | -qi::raw[h16] >> "::" >> h16 | -qi::raw[h16] >> "::" | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" >> ls32 | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" >> h16 | -qi::raw[qi::repeat(1)[(h16 >> ':')] >> h16] >> "::" | -qi::raw[qi::repeat(2)[(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 | -qi::raw[qi::repeat(2)[(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 | -qi::raw[qi::repeat(2)[(h16 >> ':')] >> h16] >> "::" >> ls32 | -qi::raw[qi::repeat(2)[(h16 >> ':')] >> h16] >> "::" >> h16 | -qi::raw[qi::repeat(2)[(h16 >> ':')] >> h16] >> "::" | -qi::raw[qi::repeat(3)[(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 | -qi::raw[qi::repeat(3)[(h16 >> ':')] >> h16] >> "::" >> ls32 | -qi::raw[qi::repeat(3)[(h16 >> ':')] >> h16] >> "::" >> h16 | -qi::raw[qi::repeat(3)[(h16 >> ':')] >> h16] >> "::" | -qi::raw[qi::repeat(4)[(h16 >> ':')] >> h16] >> "::" >> ls32 | -qi::raw[qi::repeat(4)[(h16 >> ':')] >> h16] >> "::" >> h16 | -qi::raw[qi::repeat(4)[(h16 >> ':')] >> h16] >> "::" | -qi::raw[qi::repeat(5)[(h16 >> ':')] >> h16] >> "::" >> h16 | -qi::raw[qi::repeat(5)[(h16 >> ':')] >> h16] >> "::" | -qi::raw[qi::repeat(6)[(h16 >> ':')] >> h16] >> "::"]; // ls32 = ( h16 ":" h16 ) / IPv4address ls32 %= (h16 >> ':' >> h16) | ipv4address; // h16 = 1*4HEXDIG h16 %= qi::repeat(1, 4)[qi::xdigit]; // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 // DIGIT / "25" %x30-35 dec_octet %= !(qi::lit('0') >> qi::digit) >> qi::raw[qi::uint_parser()]; // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet ipv4address %= qi::raw[dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet]]; // reg-name = *( unreserved / pct-encoded / sub-delims ) reg_name %= qi::raw[*(unreserved | pct_encoded | sub_delims)]; // TODO, host = IP-literal / IPv4address / reg-name host %= qi::raw[ip_literal | ipv4address | reg_name]; // port %= qi::ushort_; port %= qi::raw[*qi::digit]; // query = *( pchar / "/" / "?" ) query %= qi::raw[*(pchar | qi::char_("/?"))]; // fragment = *( pchar / "/" / "?" ) fragment %= qi::raw[*(pchar | qi::char_("/?"))]; // hier-part = "//" authority path-abempty / path-absolute / // path-rootless / path-empty // authority = [ userinfo "@" ] host [ ":" port ] hier_part %= ((("//" >> user_info >> '@') | "//") >> host >> -(':' >> port) >> path_abempty) | (qi::attr(iterator_range()) >> qi::attr(iterator_range()) >> qi::attr(iterator_range()) >> (path_absolute | path_rootless | path_empty)); start %= (scheme >> ':') >> hier_part >> -('?' >> query) >> -('#' >> fragment); } qi::rule::value_type()> gen_delims, sub_delims, reserved, unreserved; qi::rule pct_encoded, pchar; qi::rule segment, segment_nz, segment_nz_nc; qi::rule()> path_abempty, path_absolute, path_rootless, path_empty; qi::rule dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; qi::rule h16, ls32; qi::rule()> host, port; qi::rule()> scheme, user_info, query, fragment; qi::rule()> hier_part; // actual uri parser qi::rule()> start; }; bool parse(std::string::const_iterator first, std::string::const_iterator last, uri_parts &parts) { namespace qi = boost::spirit::qi; static detail::uri_grammar grammar; bool is_valid = qi::parse(first, last, grammar, parts); return is_valid && (first == last); } } // namespace detail } // namespace uri } // namespace network } // namespace boost cpp-netlib-0.11.2-final/boost/network/uri/uri_io.hpp000066400000000000000000000011431256751517300223470ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef __BOOST_NETWORK_URI_URI_IO_INC__ #define __BOOST_NETWORK_URI_URI_IO_INC__ #include namespace boost { namespace network { namespace uri { inline std::ostream &operator<<(std::ostream &os, const uri &uri_) { return os << uri_.string(); } } // namespace uri } // namespace network } // namespace boost #endif // __BOOST_NETWORK_URI_URI_IO_INC__ cpp-netlib-0.11.2-final/boost/network/utils/000077500000000000000000000000001256751517300207125ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/utils/base64/000077500000000000000000000000001256751517300217765ustar00rootroot00000000000000cpp-netlib-0.11.2-final/boost/network/utils/base64/encode-io.hpp000066400000000000000000000222631256751517300243560ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP #define BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP #include #include #include #include #include namespace boost { namespace network { namespace utils { // Offers an interface to the BASE64 converter from encode.hpp, which is // based on stream manipulators to be friendly to the usage with output // streams combining heterogenous output by using the output operators. // The encoding state is serialized to long and maintained in te // extensible // internal array of the output stream. // // Summarized interface - ostream manipulators and one function: // // encode(InputIterator begin, InputIterator end) // encode(InputRange const & value) // encode(char const * value) // encode_rest // clear_state // bool empty_state(std::basic_ostream & output) namespace base64 { namespace io { // force using the ostream_iterator from boost::archive to write wide // characters reliably, althoth wchar_t may not be a native character // type using namespace boost::archive::iterators; namespace detail { // Enables transferring of the input sequence for the BASE64 // encoding into // the ostream operator defined for it, which performs the // operation. It // is to be used from ostream manipulators. // // std::basic_ostream & output = ...; // output << input_wrapper(value.begin(), // value.end()); template struct input_wrapper { input_wrapper(InputIterator begin, InputIterator end) : begin(begin), end(end) {} private: InputIterator begin, end; // only encoding of an input sequence needs access to it template friend std::basic_ostream &operator<<( std::basic_ostream &output, input_wrapper input_wrapper); }; // The output stream state should be used only in a single scope // around // encoding operations. Constructor performs initialization from // the // output stream internal extensible array and destructor updates it // according to the encoding result. It inherits from the // base64::state // to gain access to its protected members and allow easy value // passing // to base64::encode. // // // std::basic_ostream & output = ...; // { // state rest(output); // base64::encode(..., ostream_iterator(output), rest); // } template struct state : public boost::network::utils::base64::state { typedef boost::network::utils::base64::state super_t; // initialize the (inherited) contents of the base64::state<> from // the // output stream internal extensible array state(std::basic_ostream &output) : super_t(), output(output) { const unsigned triplet_index_size = sizeof(super_t::triplet_index) * 8; unsigned long data = static_cast(storage()); // mask the long value with the bit-size of the triplet_index // member super_t::triplet_index = data & ((1 << triplet_index_size) - 1); // shift the long value right to remove the the triplet_index // value; // masking is not necessary because the last_encoded_value it is // the // last record stored in the data value super_t::last_encoded_value = data >> triplet_index_size; } // update the value in the output stream internal extensible array // by // the last (inherited) contents of the base64::state<> ~state() { const unsigned triplet_index_size = sizeof(super_t::triplet_index) * 8; // store the last_encoded_value in the data value first unsigned long data = static_cast(super_t::last_encoded_value); // shift the long data value left to make place for storing the // full triplet_index value there data <<= triplet_index_size; data |= static_cast(super_t::triplet_index); storage() = static_cast(data); } private: // all data of the base64::state<> must be serializable into a // long // value allocated in the output stream internal extensible array BOOST_STATIC_ASSERT(sizeof(super_t) <= sizeof(long)); // allow only the construction with an output stream (strict RAII) state(); state(state const &); std::basic_ostream &output; long &storage() { static int index = std::ios_base::xalloc(); return output.iword(index); } }; // Output operator implementing the BASE64 encoding for an input // sequence // which was wrapped by the ostream manipulator; the state must be // preserved // because multiple sequences can be sent in the ouptut by this // operator. template std::basic_ostream &operator<<(std::basic_ostream &output, input_wrapper input) { typedef typename iterator_value::type value_type; state rest(output); base64::encode(input.begin, input.end, ostream_iterator(output), rest); return output; } } // namespace detail // Encoding ostream manipulator for sequences specified by the pair of // begin // and end iterators. // // std::vector buffer = ...; // std::basic_ostream & output = ...; // output << base64::io::encode(buffer.begin(), buffer.end()) << ... // << // base64::io::encode_rest; template detail::input_wrapper encode(InputIterator begin, InputIterator end) { return detail::input_wrapper(begin, end); } // Encoding ostream manipulator processing whole sequences which // either // support begin() and end() methods returning boundaries of the // sequence // or the boundaries can be computed by the Boost::Range. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at // least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_ostream & output = ...; // output << base64::io::encode(buffer) << ... << // base64::io::encode_rest; template detail::input_wrapper::type> encode(InputRange const &value) { typedef typename boost::range_const_iterator::type InputIterator; return detail::input_wrapper(boost::begin(value), boost::end(value)); } // Encoding ostream manipulator processing string literals; the usual // expectation from their encoding is processing only the string // content // without the terminating zero character. // // std::basic_ostream & output = ...; // output << base64::io::encode("ab") << ... << // base64::io::encode_rest; inline detail::input_wrapper encode(char const *value) { return detail::input_wrapper(value, value + strlen(value)); } // Encoding ostream manipulator which finishes encoding of the // previously // processed chunks. If their total byte-length was divisible by // three, // nothing is needed, if not, the last quantum will be encoded as if // padded // with zeroes, which will be indicated by appending '=' characters to // the // output. This manipulator must be always used at the end of // encoding, // after previous usages of the encode manipulator. // // std::basic_ostream & output = ...; // output << base64::io::encode("ab") << ... << // base64::io::encode_rest; template std::basic_ostream &encode_rest(std::basic_ostream &output) { detail::state rest(output); base64::encode_rest(ostream_iterator(output), rest); return output; } // Clears the encoding state in the internal array of the output // stream. // Use it to re-use a state object in an unknown state only; Encoding // of // the last chunk must be followed by encode_rest otherwise the end of // the // input sequence may be missing in the encoded output. The // encode_rest // ensures that the rest of the input sequence will be encoded // corectly and // the '=' padding applied as necessary. The encode rest clears the // state // when finished. // // std::basic_ostream & output = ...; // output << base64::io::encode("ab") << ...; // output << clear_state; template std::basic_ostream &clear_state(std::basic_ostream &output) { detail::state rest(output); rest.clear(); return output; } // Checks if the encoding state in the internal array of the output // stream // is empty. // // std::basic_ostream & output = ...; // output << base64::io::encode("ab") << ...; // bool is_complete = base64::io::empty_state(output); template bool empty_state(std::basic_ostream &output) { detail::state rest(output); return rest.empty(); } } // namespace io } // namespace base64 } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP cpp-netlib-0.11.2-final/boost/network/utils/base64/encode.hpp000066400000000000000000000420351256751517300237500ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_ENCODE_HPP #define BOOST_NETWORK_UTILS_BASE64_ENCODE_HPP #include #include #include #include #include namespace boost { namespace network { namespace utils { // Implements a BASE64 converter working on an iterator range. // If the input sequence does not end at the three-byte boundary, the last // encoded value part is remembered in an encoding state to be able to // continue with the next chunk; the BASE64 encoding processes the input // by byte-triplets. // // Summarized interface: // // struct state { // bool empty () const; // void clear(); // } // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output, State & rest) // OutputIterator encode_rest(OutputIterator output, State & rest) // OutputIterator encode(InputRange const & input, OutputIterator output, // State & rest) // OutputIterator encode(char const * value, OutputIterator output, // state & rest) // std::basic_string encode(InputRange const & value, State & rest) // std::basic_string encode(char const * value, state & rest) // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) { // // See also http://libb64.sourceforge.net, which served as inspiration. // See also http://tools.ietf.org/html/rfc4648 for the specification. namespace base64 { namespace detail { // Picks a character from the output alphabet for another 6-bit value // from the input sequence to encode. template char encode_value(Value value) { static char const encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" "+/"; return encoding[static_cast(value)]; } } // namespace detail // Stores the state after processing the last chunk by the encoder. If // the // chunk byte-length is not divisible by three, the last (incomplete) // value // quantum canot be encoded right away; it has to wait for the next // chunk // of octets which will be processed joined (as if the trailing rest // from // the previous one was at its beinning). template struct state { state() : triplet_index(0), last_encoded_value(0) {} state(state const& source) : triplet_index(source.triplet_index), last_encoded_value(source.last_encoded_value) {} bool empty() const { return triplet_index == 0; } void clear() { // indicate that no rest has been left in the last encoded value // and no padding is needed for the encoded output triplet_index = 0; // the last encoded value, which may have been left from the last // encoding step, must be zeroed too; it is important before the // next encoding begins, because it works as a cyclic buffer and // must start empty - with zero last_encoded_value = 0; } protected: // number of the octet in the incomplete quantum, which has been // processed the last time; 0 means that the previous quantum was // complete 3 octets, 1 that just one octet was avalable and 2 that // two octets were available unsigned char triplet_index; // the value made of the previously shifted and or-ed octets which // was not completely split to 6-bit codes, because the last quantum // did not stop on the boundary of three octets Value last_encoded_value; // encoding of an input chunk needs to read and update the state template friend OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest); // finishing the encoding needs to read and clear the state template friend OutputIterator encode_rest(OutputIterator output, State& rest); }; // Encodes an input sequence to BASE64 writing it to the output iterator // and stopping if the last input tree-octet quantum was not complete, // in // which case it stores the state for the later continuation, when // another // input chunk is ready for the encoding. The encoding must be finished // by calling the encode_rest after processing the last chunk. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer.begin(), buffer.end(), appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest) { typedef typename iterator_value::type value_type; // continue with the rest of the last chunk - 2 or 4 bits which // are already shifted to the left and need to be or-ed with the // continuing data up to the target 6 bits value_type encoded_value = rest.last_encoded_value; // if the previous chunk stopped at encoding the first (1) or the // second // (2) octet of the three-byte quantum, jump to the right place, // otherwise start the loop with an empty encoded value buffer switch (rest.triplet_index) { // this loop processes the input sequence of bit-octets by bits, // shifting the current_value (used as a cyclic buffer) left and // or-ing next bits there, while pulling the bit-sextets from the // high word of the current_value for (value_type current_value;;) { case 0: // if the input sequence is empty or reached its end at the // 3-byte boundary, finish with an empty encoding state if (begin == end) { rest.triplet_index = 0; // the last encoded value is not interesting - it would not // be used, because processing of the next chunk will start // at the 3-byte boundary rest.last_encoded_value = 0; return output; } // read the first octet from the current triplet current_value = *begin++; // use just the upper 6 bits to encode it to the target alphabet encoded_value = (current_value & 0xfc) >> 2; *output++ = detail::encode_value(encoded_value); // shift the remaining two bits up to make place for the upoming // part of the next octet encoded_value = (current_value & 0x03) << 4; case 1: // if the input sequence reached its end after the first octet // from the quantum triplet, store the encoding state and finish if (begin == end) { rest.triplet_index = 1; rest.last_encoded_value = encoded_value; return output; } // read the second first octet from the current triplet current_value = *begin++; // combine the upper four bits (as the lower part) with the // previous two bits to encode it to the target alphabet encoded_value |= (current_value & 0xf0) >> 4; *output++ = detail::encode_value(encoded_value); // shift the remaining four bits up to make place for the // upoming // part of the next octet encoded_value = (current_value & 0x0f) << 2; case 2: // if the input sequence reached its end after the second octet // from the quantum triplet, store the encoding state and finish if (begin == end) { rest.triplet_index = 2; rest.last_encoded_value = encoded_value; return output; } // read the third octet from the current triplet current_value = *begin++; // combine the upper two bits (as the lower part) with the // previous four bits to encode it to the target alphabet encoded_value |= (current_value & 0xc0) >> 6; *output++ = detail::encode_value(encoded_value); // encode the remaining 6 bits to the target alphabet encoded_value = current_value & 0x3f; *output++ = detail::encode_value(encoded_value); } } return output; } // Finishes encoding of the previously processed chunks. If their total // byte-length was divisible by three, nothing is needed, if not, the // last // quantum will be encoded as if padded with zeroes, which will be // indicated // by appending '=' characters to the output. This method must be // always // used at the end of encoding, if the previous chunks were encoded by // the // method overload accepting the encoding state. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer.begin(), buffer.end(), appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode_rest(OutputIterator output, State& rest) { if (!rest.empty()) { // process the last part of the trailing octet (either 4 or 2 bits) // as if the input was padded with zeros - without or-ing the next // input value to it; it has been already shifted to the left *output++ = detail::encode_value(rest.last_encoded_value); // at least one padding '=' will be always needed - at least two // bits are missing in the finally encoded 6-bit value *output++ = '='; // if the last octet was the first in the triplet (the index was // 1), four bits are missing in the finally encoded 6-bit value; // another '=' character is needed for the another two bits if (rest.triplet_index < 2) *output++ = '='; // clear the state all the time to make sure that another call to // the encode_rest would not cause damage; the last encoded value, // which may have been left there, must be zeroed too; it is // important before the next encoding begins, because it works as // a cyclic buffer and must start empty - with zero rest.clear(); } return output; } // Encodes a part of an input sequence specified by the pair of begin // and // end iterators.to BASE64 writing it to the output iterator. If its // total // byte-length was not divisible by three, the output will be padded by // the // '=' characters. If you encode an input consisting of mutiple chunks, // use the method overload maintaining the encoding state. // // std::vector buffer = ...; // std::basic_string result; // base64::encode(buffer.begin(), buffer.end(), // std::back_inserter(result)); template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { state::type> rest; output = encode(begin, end, output, rest); return encode_rest(output, rest); } // Encodes an entire input sequence to BASE64, which either supports // begin() // and end() methods returning boundaries of the sequence or the // boundaries // can be computed by the Boost::Range, writing it to the output // iterator // and stopping if the last input tree-octet quantum was not complete, // in // which case it stores the state for the later continuation, when // another // input chunk is ready for the encoding. The encoding must be finished // by calling the encode_rest after processing the last chunk. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer, appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(InputRange const& input, OutputIterator output, State& rest) { return encode(boost::begin(input), boost::end(input), output, rest); } // Encodes an entire string literal to BASE64, writing it to the output // iterator and stopping if the last input tree-octet quantum was not // complete, in which case it stores the state for the later // continuation, // when another input chunk is ready for the encoding. The encoding // must // be finished by calling the encode_rest after processing the last // chunk. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode("ab", appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(char const* value, OutputIterator output, state& rest) { return encode(value, value + strlen(value), output, rest); } // Encodes an entire input sequence to BASE64 writing it to the output // iterator, which either supports begin() and end() methods returning // boundaries of the sequence or the boundaries can be computed by the // Boost::Range. If its total byte-length was not divisible by three, // the output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use the method overload // maintaining // the encoding state. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result; // base64::encode(buffer, std::back_inserter(result)); template OutputIterator encode(InputRange const& value, OutputIterator output) { return encode(boost::begin(value), boost::end(value), output); } // Encodes an entire string literal to BASE64 writing it to the output // iterator. If its total length (without the trailing zero) was not // divisible by three, the output will be padded by the '=' characters. // If you encode an input consisting of mutiple chunks, use the method // overload maintaining the encoding state. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result; // base64::encode("ab", std::back_inserter(result)); template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } // Encodes an entire input sequence to BASE64 returning the result as // string, which either supports begin() and end() methods returning // boundaries of the sequence or the boundaries can be computed by the // Boost::Range. If its total byte-length was not divisible by three, // the output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use other method maintaining // the encoding state writing to an output iterator. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result = base64::encode(buffer); template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } // Encodes an entire string literal to BASE64 returning the result as // string. If its total byte-length was not divisible by three, the // output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use other method maintaining // the encoding state writing to an output iterator. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result = base64::encode("ab"); template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } // The function overloads for string literals encode the input without // the terminating zero, which is usually expected, because the trailing // zero byte is not considered a part of the string value; the overloads // for an input range would wrap the string literal by Boost.Range and // encode the full memory occupated by the string literal - including // the // unwanted last zero byte. } // namespace base64 } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_ENCODE_HPP cpp-netlib-0.11.2-final/boost/network/utils/thread_pool.hpp000066400000000000000000000060731256751517300237310ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 #define BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include namespace boost { namespace network { namespace utils { typedef boost::shared_ptr io_service_ptr; typedef boost::shared_ptr worker_threads_ptr; typedef boost::shared_ptr sentinel_ptr; template struct basic_thread_pool { basic_thread_pool(std::size_t threads = 1, io_service_ptr io_service = io_service_ptr(), worker_threads_ptr worker_threads = worker_threads_ptr()) : threads_(threads), io_service_(io_service), worker_threads_(worker_threads), sentinel_() { bool commit = false; BOOST_SCOPE_EXIT_TPL( (&commit)(&io_service_)(&worker_threads_)(&sentinel_)) { if (!commit) { sentinel_.reset(); io_service_.reset(); if (worker_threads_.get()) { worker_threads_->interrupt_all(); worker_threads_->join_all(); } worker_threads_.reset(); } } BOOST_SCOPE_EXIT_END if (!io_service_.get()) { io_service_.reset(new boost::asio::io_service); } if (!worker_threads_.get()) { worker_threads_.reset(new boost::thread_group); } if (!sentinel_.get()) { sentinel_.reset(new boost::asio::io_service::work(*io_service_)); } for (std::size_t counter = 0; counter < threads_; ++counter) worker_threads_->create_thread( boost::bind(&boost::asio::io_service::run, io_service_)); commit = true; } std::size_t thread_count() const { return threads_; } void post(boost::function f) { io_service_->post(f); } ~basic_thread_pool() throw() { sentinel_.reset(); try { worker_threads_->join_all(); } catch (...) { BOOST_ASSERT(false && "A handler was not supposed to throw, but one did."); } } void swap(basic_thread_pool &other) { std::swap(other.threads_, threads_); std::swap(other.io_service_, io_service_); std::swap(other.worker_threads_, worker_threads_); std::swap(other.sentinel_, sentinel_); } protected: std::size_t threads_; io_service_ptr io_service_; worker_threads_ptr worker_threads_; sentinel_ptr sentinel_; private: basic_thread_pool(basic_thread_pool const &); // no copies please basic_thread_pool &operator=(basic_thread_pool); // no assignment // please }; typedef basic_thread_pool thread_pool; } /* utils */ } /* network */ } /* boost */ #endif /* BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 */ cpp-netlib-0.11.2-final/boost/network/version.hpp000066400000000000000000000014641256751517300217550ustar00rootroot00000000000000#ifndef BOOST_NETWORK_VERSION_HPP_20091214 #define BOOST_NETWORK_VERSION_HPP_20091214 // Copyright 2009, 2013 Dean Michael Berris // Copyright Glyn Matthews 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #define BOOST_NETLIB_VERSION_MAJOR 0 #define BOOST_NETLIB_VERSION_MINOR 11 #define BOOST_NETLIB_VERSION_INCREMENT 2 #ifndef BOOST_NETLIB_VERSION #define BOOST_NETLIB_VERSION \ BOOST_STRINGIZE(BOOST_NETLIB_VERSION_MAJOR) "." BOOST_STRINGIZE( \ BOOST_NETLIB_VERSION_MINOR) "." BOOST_STRINGIZE(BOOST_NETLIB_VERSION_INCREMENT) #endif // BOOST_NETLIB_VERSION #endif // BOOST_NETWORK_VERSION_HPP_20091214 cpp-netlib-0.11.2-final/cppnetlibConfig.cmake.in000066400000000000000000000016071256751517300214540ustar00rootroot00000000000000# - Config file for the cppnetlib package # It defines the following variables # CPPNETLIB_INCLUDE_DIRS - include directories for cppnetlib # CPPNETLIB_LIBRARIES - libraries to link against # CPPNETLIB_EXECUTABLE - the bar executable # Compute paths get_filename_component(CPPNETLIB_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) set(CPPNETLIB_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") # Our library dependencies (contains definitions for IMPORTED targets) if( NOT TARGET cppnetlib-client-connections AND NOT TARGET cppnetlib-server-parsers AND NOT TARGET cppnetlib-uri AND NOT CPPNETLIB_BINARY_DIR) include("${CPPNETLIB_CMAKE_DIR}/cppnetlibTargets.cmake") endif() # These are IMPORTED targets created by cppnetlibTargets.cmake set(CPPNETLIB_LIBRARIES cppnetlib-client-connections cppnetlib-server-parsers cppnetlib-uri) #set(CPPNETLIB_EXECUTABLE ...) # maybe the examples? cpp-netlib-0.11.2-final/cppnetlibConfigVersion.cmake.in000066400000000000000000000006041256751517300230160ustar00rootroot00000000000000set(PACKAGE_VERSION "@CPPNETLIB_VERSION_STRING@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif()cpp-netlib-0.11.2-final/index.html000066400000000000000000000014701256751517300167320ustar00rootroot00000000000000 Automatic redirection failed, please go to index.html. cpp-netlib-0.11.2-final/libs/000077500000000000000000000000001256751517300156645ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/000077500000000000000000000000001256751517300166135ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/To-Do.txt000066400000000000000000000007301256751517300202760ustar00rootroot00000000000000To Do list for Boost.Mime: General: * Finish the test suites ** Compare results to python parser ** Try to parse some bad mime inputs --> Added 0019-NoBoundary test * Integrate into cpp-netlib * Write some docs Specific: * Rename make_mime into something better. Parse, Encode? --> Changed the name to 'parse_mime', and made the stream and iterator versions use the same name * Start using boost::exception * Look into making the parsing restartable * Figure out how to cpp-netlib-0.11.2-final/libs/mime/doc/000077500000000000000000000000001256751517300173605ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/doc/mime.qbk000066400000000000000000000043441256751517300210130ustar00rootroot00000000000000[/ (C) Copyright 2010 Marshall Clow Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ] [article C++ Mime Library [quickbook 1.4] [version 0.5] [authors [Clow, Marshall]] [copyright 2010 Marshall Clow] [purpose C++ library for MIME parsing, manipulation and printing] [category text] [license Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at [@http://www.boost.org/LICENSE_1_0.txt]) ] ] [def __boost__ [@http://www.boost.org/ the Boost C++ Libraries]] [def __boost_org__ [@http://www.boost.org/]] [def __boost_asio__ [@http://www.boost.org/libs/asio/index.html Boost.Asio]] [def __boost_system__ [@http://www.boost.org/libs/system/index.html Boost.System]] [def __boost_type_traits__ [@http://www.boost.org/libs/type_traits/index.html Boost.TypeTraits]] [def __boost_doc__ [@http://www.boost.org/doc/libs/]] [def __pion__ [@http://www.pion.org/projects/pion-network-library the Pion Network Library]] [def __cnl__ C++ Network Library] [def __message__ `basic_message`] [def __uri__ `basic_uri`] [def __python__ [@http://www.python.org Python]] [def __libcurl__ [@http://curl.haxx.se/ libcurl]] [def __mozilla_netlib__ [@http://www.mozilla.org/projects/netlib/ mozilla-netlib]] [def __sf_cpp_netlib__ [@http://sourceforge.net/projects/cpp-netlib/ sourceforge]] [def __github__ [@http://github.com/mikhailberis/cpp-netlib github]] [def __default_constructible__ [@http://www.boost.org/doc/html/DefaultConstructible.html DefaultConstructible]] [def __copy_constructible__ [@http://www.boost.org/doc/html/CopyConstructible.html CopyConstructible]] [def __assignable__ [@http://www.boost.org/doc/html/Assignable.html Assignable]] [def __equality_comparable__ [@http://www.boost.org/doc/html/Assignable.html Assignable]] [def __quick_start__ quick start] [include quick_start.qbk] #[include intro.qbk] #[include using.qbk] #[/include architecture.qbk] #[include message.qbk] #[include uri.qbk] #[include protocol.qbk] #[include examples.qbk] #[include reference.qbk] #[include acknowledgements.qbk] #[include appendices.qbk] #[include contributors.qbk] cpp-netlib-0.11.2-final/libs/mime/doc/quick_start.qbk000066400000000000000000000004011256751517300224030ustar00rootroot00000000000000[/ (C) Copyright 2010 Marshall Clow Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ] [section:quick_start Quick Start] [endsect] [/ quick_start] cpp-netlib-0.11.2-final/libs/mime/example/000077500000000000000000000000001256751517300202465ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/example/basic_parsing.cpp000066400000000000000000000100601256751517300235530ustar00rootroot00000000000000// // Copyright Marshall Clow 2009-2010 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // #include #include #include #include #include struct my_traits { typedef std::string string_type; // typedef std::pair < std::string, string_type > header_type; typedef std::string body_type; }; // typedef boost::mime::mime_part<> mime_part; typedef boost::mime::basic_mime mime_part; template void DumpContainer(std::ostream &out, const std::string &prefix, const Container &c) { out << prefix << ' '; if (c.size() < 10) { for (typename Container::const_iterator iter = c.begin(); iter != c.end(); ++iter) out << (int)*iter << ' '; } else { for (int i = 0; i < 5; i++) out << int(c.begin()[i]) << ' '; out << "... "; for (int i = 0; i < 5; i++) out << int(c.rbegin()[i]) << ' '; } out << std::endl; } void DumpStructure(std::ostream &out, const char *title, const mime_part &mp, std::string prefix) { std::string content_type = mp.get_content_type(); if (NULL != title) out << prefix << "Data from: " << title << std::endl; out << prefix << "Content-Type: " << content_type << std::endl; out << prefix << "There are " << std::distance(mp.header_begin(), mp.header_end()) << " headers" << std::endl; size_t subpart_count = std::distance(mp.subpart_begin(), mp.subpart_end()); switch (mp.get_part_kind()) { case mime_part::simple_part: if (subpart_count != 0) out << str(boost::format("%s ### %d subparts on a simple (%s) type!") % prefix % subpart_count % content_type) << std::endl; out << prefix << "The body is " << mp.body_size() << " bytes long" << std::endl; DumpContainer(out, prefix, *mp.body()); break; case mime_part::multi_part: break; case mime_part::message_part: if (boost::iequals(content_type, "message/delivery-status")) out << prefix << "The body is " << mp.body_size() << " bytes long" << std::endl; else if (1 != subpart_count) out << str(boost::format("%s ### %d subparts on a message (%s) type!") % subpart_count % prefix % content_type) << std::endl; break; } if (subpart_count != 0) { out << prefix << "There are " << std::distance(mp.subpart_begin(), mp.subpart_end()) << " sub parts" << std::endl; for (mime_part::constPartIter iter = mp.subpart_begin(); iter != mp.subpart_end(); ++iter) DumpStructure(out, NULL, **iter, prefix + " "); } } int main(int argc, char *argv[]) { if (argc == 1) std::cerr << "Usage: basic_parsing " << std::endl; for (int i = 1; i < argc; ++i) { boost::shared_ptr rmp; try { std::ifstream in(argv[i]); if (!in) { std::cerr << "Can't open file " << argv[i] << std::endl; continue; } in >> std::noskipws; std::cout << "**********************************" << std::endl; rmp = mime_part::parse_mime(in); } catch (const boost::mime::mime_parsing_error &err) { std::cout << "Caught an error parsing '" << argv[i] << "'" << std::endl; std::cout << " " << err.what() << std::endl; continue; } catch (const boost::exception &berr) { std::cout << "Caught an boost error parsing '" << argv[i] << "'" << std::endl; // std::cout << " " << berr.what () << std::endl; continue; } try { DumpStructure(std::cout, argv[i], *rmp, std::string()); // std::ofstream out ( (std::string ( argv[i] ) + "-Results").c_str (), // std::ios::binary ); // out << rmp; } catch (const std::runtime_error &err) { std::cout << "Caught an error writing '" << argv[i] << "'" << std::endl; std::cout << " " << err.what() << std::endl; continue; } } return 0; } cpp-netlib-0.11.2-final/libs/mime/example/basic_usage.cpp000066400000000000000000000041101256751517300232130ustar00rootroot00000000000000// // Copyright Marshall Clow 2009-2010 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // #include #include #include #include #include struct my_traits { typedef std::string string_type; // typedef std::pair < std::string, string_type > header_type; typedef std::string body_type; }; typedef boost::mime::basic_mime mime_part; int main(int argc, char* argv[]) { // (1) a really simple part mime_part mp("text", "plain"); mp.set_body("Hello World\n", 12); std::cout << mp; // Three trips around the house before we go through the door. // Make a part, copy it onto the heap, and wrap it into a shared pointer. std::cout << "*******" << std::endl; std::string str("Hi Mom!\n"); boost::shared_ptr mp0(new mime_part( mime_part::make_simple_part("text", "html", str.begin(), str.end()))); std::cout << mp0; std::cout << "*******" << std::endl; boost::shared_ptr mp1(new mime_part("text", "plain")); mp1->set_body("This is a test.....\n", 20); mp1->append_phrase_to_content_type("charset", "usascii"); std::cout << mp1; // Build a multipart mime_part mp2("multipart", "multiple"); mp2.set_body("This is the body of a multipart\n", 32); mp2.append_part(mp0); mp2.append_part(mp1); // stream it out to a string, then make a new part from the string std::ostringstream os1, os2; os1 << mp2; std::istringstream is(os1.str()); is >> std::noskipws; boost::shared_ptr strmp = mime_part::parse_mime(is); os2 << strmp; if (os1.str() == os2.str()) std::cout << "Strings match!!" << std::endl; else { // Write the differences out to files for examination std::cout << "##Strings differ!!" << std::endl; std::ofstream t1("test1.out", std::ios::binary); t1 << os1.str(); std::ofstream t2("test2.out", std::ios::binary); t2 << os2.str(); } return 0; } cpp-netlib-0.11.2-final/libs/mime/test/000077500000000000000000000000001256751517300175725ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/test/CMakeLists.txt000066400000000000000000000012661256751517300223370ustar00rootroot00000000000000include_directories(${CPP-NETLIB_SOURCE_DIR}) file ( COPY TestMessages DESTINATION ${CMAKE_CURRENT_BINARY_DIR} ) #This test causes a "too many sections" error on Windows MinGW64 #(MSVC has /bigobj, MinGW does not) if (NOT(${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows")) if ( Boost_FOUND ) add_executable ( mime-roundtrip mime-roundtrip.cpp ) target_link_libraries ( mime-roundtrip ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( mime-roundtrip PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test ( mime-roundtrip ${CPP-NETLIB_BINARY_DIR}/tests/mime-roundtrip ) endif () endif() cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/000077500000000000000000000000001256751517300222015ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/.gitattributes000066400000000000000000000000111256751517300250640ustar00rootroot00000000000000* -crlf cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/00000001000066400000000000000000000046431256751517300230130ustar00rootroot00000000000000Resent-To: mail.app@flagg2.qualcomm.com Resent-From: win-eudora-bugs@flagg2.qualcomm.com Resent-Message-Id: Resent-Date: Mon, 1 Nov 2004 15:38:13 -0800 Received: from flagg2.qualcomm.com [129.46.154.229] by localhost with IMAP (fetchmail-6.2.5) for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:25 -0800 (PST) Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; Mon, 1 Nov 2004 15:38:13 -0800 Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA1NcAcH015308 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Mon, 1 Nov 2004 15:38:11 -0800 (PST) Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA1Nc8HJ019370 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Mon, 1 Nov 2004 15:38:09 -0800 (PST) Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA1Nc7Rg028808 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) Received: from coyote.rain.org (coyote.rain.org [198.68.144.2]) by isengard.qualcomm.com with ESMTP id iA1Nc7uA020987 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) Received: from sanders.rain.org (maxmp-189.rain.org [198.68.144.189]) by coyote.rain.org (Postfix) with ESMTP id 648227775 for ; Mon, 1 Nov 2004 15:38:06 -0800 (PST) Message-Id: <5.0.2.1.2.20041101153017.00a26ec0@rain.org> X-Sender: maia3@rain.org X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 Date: Mon, 01 Nov 2004 15:31:46 -0800 To: win-eudora6-bugs@qualcomm.com From: Maia Subject: New Bugs Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; format=flowed X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 Just now, without any reason, an email of mine was turned into a mixture of text and directions and numbers and letters and is now unusable. Do you know why this is happening? Thanks, Maia cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/00000019000066400000000000000000000073531256751517300230250ustar00rootroot00000000000000Resent-To: mail.app@flagg2.qualcomm.com Resent-From: win-eudora-bugs@flagg2.qualcomm.com Resent-Message-Id: Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 Received: from flagg2.qualcomm.com [129.46.154.229] by localhost with IMAP (fetchmail-6.2.5) for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; Mon, 1 Nov 2004 16:01:16 -0800 Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Mon, 1 Nov 2004 16:01:15 -0800 (PST) Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) From: Mail Delivery Subsystem Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> To: MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="iA201CuA023535.1099353672/isengard.qualcomm.com" Subject: Returned mail: see transcript for details Auto-Submitted: auto-generated (failure) X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 This is a MIME-encapsulated message --iA201CuA023535.1099353672/isengard.qualcomm.com The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) from [210.193.18.250] ----- The following addresses had permanent fatal errors ----- (reason: 550 5.6.1 Prohibited attachment type) ----- Transcript of session follows ----- ... while talking to hobbiton.qualcomm.com.: >>> DATA <<< 550 5.6.1 Prohibited attachment type 554 5.0.0 Service unavailable --iA201CuA023535.1099353672/isengard.qualcomm.com Content-Type: message/delivery-status Reporting-MTA: dns; isengard.qualcomm.com Received-From-MTA: DNS; [210.193.18.250] Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) Final-Recipient: RFC822; win-eudora6-bugs@eudora.com Action: failed Status: 5.6.1 Remote-MTA: DNS; hobbiton.qualcomm.com Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) --iA201CuA023535.1099353672/isengard.qualcomm.com Content-Type: text/rfc822-headers Return-Path: Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> From: win-eudora6-bugs@eudora.com To: win-eudora6-bugs@eudora.com Subject: Re: Excel file Date: Tue, 2 Nov 2004 08:00:34 +0800 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0001_00000AE6.000070CC" X-Priority: 3 X-MSMail-Priority: Normal --iA201CuA023535.1099353672/isengard.qualcomm.com-- cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/00000431000066400000000000000000000177411256751517300230250ustar00rootroot00000000000000Marshall-Sez: This message has nested multiparts; with the last part of a multipart being another multipart Resent-To: mail.app@flagg2.qualcomm.com Resent-From: eudora-suggest@flagg2.qualcomm.com Resent-Message-Id: Resent-Date: Mon, 1 Nov 2004 22:33:29 -0800 Received: from flagg2.qualcomm.com [129.46.154.229] by localhost with IMAP (fetchmail-6.2.5) for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:39:31 -0800 (PST) Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; Mon, 1 Nov 2004 22:33:29 -0800 Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA26XQcH013328 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Mon, 1 Nov 2004 22:33:26 -0800 (PST) Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA26XNHJ013973 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Mon, 1 Nov 2004 22:33:24 -0800 (PST) Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA26XMha015651 for ; Mon, 1 Nov 2004 22:33:22 -0800 (PST) Received: from d60-65-159-220.col.wideopenwest.com (d60-65-159-220.col.wideopenwest.com [65.60.220.159]) by isengard.qualcomm.com with ESMTP id iA26XFuA029259 for ; Mon, 1 Nov 2004 22:33:16 -0800 (PST) Received: from lopezclub.com (lopezclub-com.mr.outblaze.com [205.158.62.177]) by d60-65-159-220.col.wideopenwest.com with esmtp id 1F1D2A4AC2 for ; Tue, 02 Nov 2004 00:35:33 -0600 Message-ID: <010001c4c0a6$2e00ef5b$f3fa62fd@lopezclub.com> From: "Coarsest A. Spading" To: Eudora Subject: =?windows-1251?B?zeUg5OD+8iDv8O717uTgIOru4uDr5fD7Pw==?= Date: Tue, 02 Nov 2004 00:35:33 -0600 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0036_D092C96B.3CE29AF1" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1106 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 X-RAV-Antivirus: This e-mail has been scanned for viruses on host: d60-65-159-220.col.wideopenwest.com X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.6 X-PerlMx-Spam: Gauge=XXXXXXXXXIIIIII, Probability=96%, Report='MR_OUTBLAZE 5, IMGSPAM_BODY 3.2, RCVD_IN_CBL 3, __SANE_MSGID 0, __TO_MALFORMED_2 0, __MIME_VERSION 0, __NEXTPART_NORMAL 0, __NEXTPART_ALL 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_X_PRIORITY 0, __HAS_MSMAIL_PRI 0, __OUTLOOK_MUA_1 0, __HAS_X_MAILER 0, SUBJ_FULL_OF_8BITS 0, __HIGHBITS 0, __IMGSPAM_BODY 0, __TAG_EXISTS_BODY 0, __TAG_EXISTS_META 0, __TAG_EXISTS_HTML 0, HTML_FONT_COLOR_BLUE 0, __TAG_EXISTS_HEAD 0, __IMGSPAM_BODY_1 0, HTML_90_100 0, __HAS_MSGID 0, __OUTLOOK_MUA 0, IMGSPAM_BODY_1 0, __OUTLOOK_MSGID_1 0' X-Maybe-Spam: X-Maybe-Spam This is a multi-part message in MIME format. ------=_NextPart_000_0036_D092C96B.3CE29AF1 Content-Type: multipart/related; type="multipart/alternative"; boundary="----=_NextPart_001_0037_D092C96B.3CE29AF1" ------=_NextPart_001_0037_D092C96B.3CE29AF1 Content-Type: image/gif; name="ani.gif" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="ani.gif" Content-ID: R0lGODlh/ABLAMQAAP///wAAgAAA/wAAADMzmRERiEREoVVVqoiIw+7u9szM5SIikLu73d3d 7qqq1GZmsnd3u5mZzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACH5BAAAAAAALAAAAAD8AEsAAAX/ICCOZGmeaKqubOu+cCzPdG2LCUQEQXEwt6BwyIoYCrzk gsgcGpHJwJLIIzmg0cCjye3GGossjwD0mltgcYDMrOKQi3IigkSc73jAooBQ5P8re313bgAP UiYKiICMQg4Bfo2SI4+RhAEjYQ4nhSJGSQeWIp0ApJ2kB1VqSSOopIkHcHYlCQ9IPg0kBwQA DDtrsyQKqWIsDbY9D7mjq5gqw7Imx7fKury+Y8EknzyhJYVXzswjCgYnirwjv1ll4ySm4qXx iqrNrfOsKY9Z6SINWEk2iSDw4FCWAst62VOxL0oBgc3imWiYpB8AijweqisoBiGJdVHaycOR zx2KBAiQ/7RDsGZZgx0W4X2L12ndTE7xbJ7kASEBAAU7gtXxeayHz1Jh2ABoYGARgB0Pjpo8 kQDJAZ8JUhWQOjVFAp4+gQaYVTXAVQBZjY5KWoapU5YEXMJ85yxCgAg3cWYUGSYh2lMSZd6j FKBpYIkmHxlOAcGssEUstQFoDIHZlI93u45kXLhE08p0WzQ+8HhKY3MkPls2sQOvngB+v9J0 RuDyYL1j/OIMzfu2yTD08goH/kodpBRNTXxNx0MgCQZrRCAxUdy4SIUWN6/YIarEjuvQmQdw PiK8CsB/JWtHwUCr7gQMEBxB33uqG5akBefFv144bjWaudMYAaJUF6B+5yFW3/9t1ZECn3xQ hBbLbizwJwIDYRTjW1foleUTgoN52N+CMy3UoDiGaYhCcSCuqOCGDL5YCIYA3tMchT8ZwBVv 0EkBQQQKyLYgglUcMkuLIxkZ4JJMipAcjksBZOCI/U0Jo3+3PUmdMz0u8GOQ6B1C3m9auCiC Jv6BCJgiBcDIIiQ9XGlcd5hdV8IhdiqWWplNfleCeSSewF0Kfj4XnSEB5NnZa2PSV6hv+4yJ KGn9sTQbloA15RySPGgqpwiNbTHCV6YtWt6ij2T3mmsA2BXTi6Ca6mQAoH1aQqgkkBoraiOo dtGhJIThGimW8sbmdjwgcNQwPCwThqi1JCGVmrM5VaX/gkoEStJYIohFFhIG5MKAQQk1pRQ2 FiHh15RlnZXWVljuxO1PQb1hFlZaSWVuGehmwme0PEwrziG1ogBSEhp5IgYEYbQTUY3yHOcm tjwUCOuv/FihxpgH95AQwfGWgNGNIZ8wskUjj+ddRwnZlQXDiW6IhMATpUiAetgUBgR0vD6s YqeYUsxrkz8Rs4B6tUDxwwkI/LKAqN3GWTIJ0ySzI9HCGK1e1QVExbTTUJf3iwE7m9oJSz1f nIeVk7Tt9ttwu8B23HTXbTcjc9+t995835B334AHLviWgxdu+OGIJ6744ow37vjjkEcu+eSU Bz7A5Zg3PgAAm+stwOefnyBA/wmggw5A6aafjvoIpUfe+QivJ5655ySMXvvpKNhuuwm7izB6 770zHjvnlccdPPC488567qQr//jwnb8u/ewiUM/55SdIDzv22XNfvffaY8499cMnb37ovrO+ +/rN37588OnH7/zy7d/+O/18iw/+97BX37//xAMgCbQXwAL+L4AEjB4BC1g+/K2Pfb6DoPnk Jz8JUhB16Dve/NRXQcBBD4D7Y+D/FnjA8plQBdHjnwBJqLz76Q5394OhDOvXQQpOEH4RbB0N HYi/vX2QeJtL4PZmx8Lrkc96AhwgEYFYQvGpwIXJg+ILobhD3WGwhxN0Xxa3WEMu1u2H4xvh AUtoAv8hJvGMIrzeCsf4RBlOcYZS3GAU66dB0WnRi+fD4t3AmMI0prGIZvQeGRGowDUaMgUW TKQeb2jD9MEPh4xspBYtqDf9LTCIlhyiEht4ySB2L3bY66MfjchGHpqyiw9MHRcxGDpW2vB3 q8uj+tDnuB8W75a4LGMJGvg4Vvryl8AMpjCHSUxh5vKYyEymMpfJzGY685nQjKY0p0nNalrz mtjMpja3yc1uevOb4AynOMdJznKa85zoTKc618nOdrrznfCMpzznSc96WlMR5mgAMQ6QELHw iRlRmBWdijYGh2WBEr8ggKT8sc+E6LMbukHoGJzjAKepx54naAoQANKmn2T/zKMHVcjQopaF TdAjoACwVBRYRQKOjsClJlBpEvDisigUDKPKQYSFUmGHVIAmFXh5BKVKEIYdpUJULFmCUE1Q BxGwpKMk2Cm3pKqepqY0Tk1xTXDeuYoU2KUyTYkEPtfTmcicoDEsBYCWRmLWNCEmrFEzB1w9 OlKyIsYutmFnV1GQCiCgBz2pyJABLAGdoZ4jOoHtVCSaMgu0EW4w9NlTY2VlGI/Ik21Ftata +WSQp4ghEroilMo65oeXREFVmo3sCExbkRJAoQAD1avaNoOekwb0CK45RD+qkwZR4VYEuo2S QyL610uV4B/DNUFwLztbN9CnHGu4AlR7Uxzkhu0my4x16qFUNBL6RCG7V0Xt38jJNjfMday0 6ExTaKYZ5BZsvZA17nclNtbzLoq7VTgCe+PJth3kgqqbBUICPJUKSh2CUsthamZ04ZhJAcCq SY1pg3l6VUpR2LXzinCBgdtg/hqXwWWAaWNO6w+OHqWwdwIQchHmk5EtFKYPdojJxLCJFWdk GeP9pmoVBpq0mCUhEIjGag3DzxGgFcMacsuPxVbQkzR0VE8+Qc6UspQoU8meoSVCZnG6zLkK QRGG5TIy0SsEL4v5zGiOWwgAADs= ------=_NextPart_001_0037_D092C96B.3CE29AF1 Content-Type: multipart/alternative; boundary="----=_NextPart_002_0038_D092C96B.3CE29AF1" ------=_NextPart_002_0038_D092C96B.3CE29AF1 Content-Type: text/plain; charset=windows-1251 Content-Transfer-Encoding: quoted-printable =c2=e4=ee=e1=e0=e2=ee=ea =ea =f0=e0=f1=f1=ea=e0=e7=e0=ec =ee =f1=f2=f0= =e0=ed=ed=fb=f5 =ef=f0=ee=e8=f1=f8=e5=f1=f2=e2=e8=ff=f5 ------=_NextPart_002_0038_D092C96B.3CE29AF1 Content-Type: text/html; charset=windows-1251 Content-Transfer-Encoding: quoted-printable
 
 
=f1=ee=e2=f0=e5=ec=e5=ed=ed=e0=ff =ed=e0=f3=ea=e0=2e = =c8=ed=ee=e3=e4=e0 =f2=e0=ea=ee=e9 =ea=eb=fe=f7 =e1=fc=e5=f2 =e8=e7
------=_NextPart_002_0038_D092C96B.3CE29AF1-- ------=_NextPart_001_0037_D092C96B.3CE29AF1-- ------=_NextPart_000_0036_D092C96B.3CE29AF1-- cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/00000975000066400000000000000000000112651256751517300230350ustar00rootroot00000000000000Resent-To: mail.app@flagg2.qualcomm.com Resent-From: eudora-suggest@flagg2.qualcomm.com Resent-Message-Id: Resent-Date: Tue, 2 Nov 2004 08:05:31 -0800 Received: from flagg2.qualcomm.com [129.46.154.229] by localhost with IMAP (fetchmail-6.2.5) for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:40:47 -0800 (PST) Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; Tue, 2 Nov 2004 08:05:31 -0800 Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA2G5TcH006140 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Tue, 2 Nov 2004 08:05:30 -0800 (PST) Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA2G5R9A004119 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Tue, 2 Nov 2004 08:05:28 -0800 (PST) Received: from mailserver.internal.evanstech.com ([216.235.152.49]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA2G5QBU029487 for ; Tue, 2 Nov 2004 08:05:26 -0800 (PST) From: postmaster@evanstech.com To: eudora-suggest@qualcomm.com Date: Tue, 2 Nov 2004 11:04:00 -0500 MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter" X-DSNContext: 335a7efd - 4457 - 00000001 - 80040546 Message-ID: Subject: Delivery Status Notification (Failure) X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.8 X-PerlMx-Spam: Gauge=XXXXX, Probability=50%, Report='VBOUNCE 5, __TO_MALFORMED_2 0, __MIME_VERSION 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_MSGID 0, __SANE_MSGID 0, __UNUSABLE_MSGID 0, __VIRUS_MYDOOM_1 0, NO_REAL_NAME 0' This is a MIME-formatted message. Portions of this message may be unreadable without a MIME-capable mail program. --9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit ------------------ Virus Warning Message (on echelon) Found virus WORM_SWASH.A in file message.pif (in message.zip) The uncleanable file is deleted. Visit http://qualnet.qualcomm.com/it/virus for more information --------------------------------------------------------- --9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter Content-Type: text/plain; charset=unicode-1-1-utf-7 This is an automatically generated Delivery Status Notification. Delivery to the following recipients failed. john@evanstech.com --9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter Content-Type: message/delivery-status Reporting-MTA: dns;mailserver.internal.evanstech.com Received-From-MTA: dns;qualcomm.com Arrival-Date: Tue, 2 Nov 2004 11:03:49 -0500 Final-Recipient: rfc822;john@evanstech.com Action: failed Status: 5.1.1 --9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter Content-Type: message/rfc822 Received: from qualcomm.com ([80.231.132.37] RDNS failed) by mailserver.internal.evanstech.com with Microsoft SMTPSVC(5.0.2195.6713); Tue, 2 Nov 2004 11:03:49 -0500 From: eudora-suggest@qualcomm.com To: john@evanstech.com Subject: Status Date: Tue, 2 Nov 2004 17:03:42 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0007_BF11B844.031F7FC2" X-Priority: 3 X-MSMail-Priority: Normal Return-Path: eudora-suggest@qualcomm.com Message-ID: X-OriginalArrivalTime: 02 Nov 2004 16:03:50.0928 (UTC) FILETIME=[8B44D100:01C4C0F5] This is a multi-part message in MIME format. ------=_NextPart_000_0007_BF11B844.031F7FC2 Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: 7bit The message cannot be represented in 7-bit ASCII encoding and has been sent as a binary attachment. ------=_NextPart_000_0007_BF11B844.031F7FC2 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit ------------------ Virus Warning Message (on echelon) message.zip is removed from here because it contains a virus. --------------------------------------------------------- ------=_NextPart_000_0007_BF11B844.031F7FC2-- --9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter-- cpp-netlib-0.11.2-final/libs/mime/test/TestMessages/0019-NoBoundary000066400000000000000000000072551256751517300246040ustar00rootroot00000000000000Resent-To: mail.app@flagg2.qualcomm.com Resent-From: win-eudora-bugs@flagg2.qualcomm.com Resent-Message-Id: Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 Received: from flagg2.qualcomm.com [129.46.154.229] by localhost with IMAP (fetchmail-6.2.5) for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; Mon, 1 Nov 2004 16:01:16 -0800 Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Mon, 1 Nov 2004 16:01:15 -0800 (PST) Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) From: Mail Delivery Subsystem Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> To: MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status Subject: Returned mail: see transcript for details Auto-Submitted: auto-generated (failure) X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 This is a MIME-encapsulated message --iA201CuA023535.1099353672/isengard.qualcomm.com The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) from [210.193.18.250] ----- The following addresses had permanent fatal errors ----- (reason: 550 5.6.1 Prohibited attachment type) ----- Transcript of session follows ----- ... while talking to hobbiton.qualcomm.com.: >>> DATA <<< 550 5.6.1 Prohibited attachment type 554 5.0.0 Service unavailable --iA201CuA023535.1099353672/isengard.qualcomm.com Content-Type: message/delivery-status Reporting-MTA: dns; isengard.qualcomm.com Received-From-MTA: DNS; [210.193.18.250] Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) Final-Recipient: RFC822; win-eudora6-bugs@eudora.com Action: failed Status: 5.6.1 Remote-MTA: DNS; hobbiton.qualcomm.com Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) --iA201CuA023535.1099353672/isengard.qualcomm.com Content-Type: text/rfc822-headers Return-Path: Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> From: win-eudora6-bugs@eudora.com To: win-eudora6-bugs@eudora.com Subject: Re: Excel file Date: Tue, 2 Nov 2004 08:00:34 +0800 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0001_00000AE6.000070CC" X-Priority: 3 X-MSMail-Priority: Normal --iA201CuA023535.1099353672/isengard.qualcomm.com-- cpp-netlib-0.11.2-final/libs/mime/test/mime-roundtrip.cpp000066400000000000000000000061371256751517300232600ustar00rootroot00000000000000/* Read in a mime structure, parse it, and write it back to a file with the same name as the input file, but with "-Results" appended to the name We don't just write to stdout, because we want to read/write binary data, and stdout on some systems eats CRLF, and turns them into newlines. Returns 0 for success, non-zero for failure */ #include #include #ifdef BOOST_TEST_DYN_LINK #define BOOST_TEST_ALTERNATIVE_INIT_API #endif #include #include #include #include #include #include #include namespace { std::string readfile(const char *fileName) { std::ifstream in(fileName); if (!in) { std::cerr << std::string("Can't open file: ") + fileName << std::endl; throw std::runtime_error(std::string("Can't open file: ") + fileName); } std::istreambuf_iterator src(in); std::istreambuf_iterator eof; std::string retVal; in >> std::noskipws; std::copy(src, eof, std::back_inserter(retVal)); return retVal; } struct my_traits { typedef std::string string_type; // typedef std::pair < std::string, string_type > header_type; typedef std::string body_type; }; // using namespace boost::mime; typedef boost::mime::basic_mime mime_part; typedef boost::shared_ptr smp; smp to_mime(const char *fileName) { std::ifstream in(fileName); if (!in) { std::cerr << std::string("Can't open file: ") + fileName << std::endl; throw std::runtime_error(std::string("Can't open file: ") + fileName); } in >> std::noskipws; return mime_part::parse_mime(in); } std::string from_mime(smp mp) { std::ostringstream oss; oss << *mp; return oss.str(); } void test_roundtrip(const char *fileName) { smp mp; BOOST_REQUIRE_NO_THROW(mp = to_mime(fileName)); BOOST_CHECK_EQUAL(readfile(fileName), from_mime(mp)); } } using namespace boost::unit_test; #ifdef BOOST_TEST_DYN_LINK bool init_unit_test() #else test_suite *init_unit_test_suite(int, char **) #endif { framework::master_test_suite().add( BOOST_TEST_CASE(boost::bind(test_roundtrip, "TestMessages/00000001"))); framework::master_test_suite().add( BOOST_TEST_CASE(boost::bind(test_roundtrip, "TestMessages/00000019"))); framework::master_test_suite().add( BOOST_TEST_CASE(boost::bind(test_roundtrip, "TestMessages/00000431"))); framework::master_test_suite().add( BOOST_TEST_CASE(boost::bind(test_roundtrip, "TestMessages/00000975"))); // Following test is removed because the file it used often tripped // false-positives when scanned by virus checkers. // framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( // test_roundtrip, "TestMessages/00001136" ))); // test cases that fail // framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( // test_roundtrip, "TestMessages/0019-NoBoundary" ))); return #ifdef BOOST_TEST_DYN_LINK true; #else 0; #endif } #ifdef BOOST_TEST_DYN_LINK int main(int argc, char *argv[]) { return unit_test_main(&init_unit_test, argc, argv); } #endif cpp-netlib-0.11.2-final/libs/mime/test/mime-structure.cpp000066400000000000000000000075241256751517300232730ustar00rootroot00000000000000/* Read in a mime structure, parse it, dump the structure to stdout Returns 0 for success, non-zero for failure */ #include #include #include #include #include struct my_traits { typedef std::string string_type; // typedef std::pair < std::string, string_type > header_type; typedef std::string body_type; }; typedef boost::mime::basic_mime mime_part; template void DumpContainer(std::ostream &out, const std::string &prefix, const Container &c) { out << prefix << ' '; if (c.size() < 10) { for (typename Container::const_iterator iter = c.begin(); iter != c.end(); ++iter) out << (int)*iter << ' '; } else { for (int i = 0; i < 5; i++) out << int(c.begin()[i]) << ' '; out << "... "; for (int i = 0; i < 5; i++) out << int(c.rbegin()[i]) << ' '; } out << std::endl; } void DumpStructure(std::ostream &out, const char *title, const mime_part &mp, std::string prefix) { std::string content_type = mp.get_content_type(); if (NULL != title) out << prefix << "Data from: " << title << std::endl; out << prefix << "Content-Type: " << content_type << std::endl; out << prefix << "There are " << std::distance(mp.header_begin(), mp.header_end()) << " headers" << std::endl << std::flush; size_t subpart_count = std::distance(mp.subpart_begin(), mp.subpart_end()); switch (mp.get_part_kind()) { case mime_part::simple_part: if (subpart_count != 0) out << str(boost::format("%s ### %d subparts on a simple (%s) type!") % prefix % subpart_count % content_type) << std::endl; out << prefix << "The body is " << mp.body_size() << " bytes long" << std::endl; DumpContainer(out, prefix, *mp.body()); break; case mime_part::multi_part: break; case mime_part::message_part: if (boost::iequals(content_type, "message/delivery-status")) out << prefix << "The body is " << mp.body_size() << " bytes long" << std::endl; else if (1 != subpart_count) out << str(boost::format("%s ### %d subparts on a message (%s) type!") % subpart_count % prefix % content_type) << std::endl; break; } if (subpart_count != 0) { out << prefix << "There are " << std::distance(mp.subpart_begin(), mp.subpart_end()) << " sub parts" << std::endl << std::flush; for (mime_part::constPartIter iter = mp.subpart_begin(); iter != mp.subpart_end(); ++iter) DumpStructure(out, NULL, **iter, prefix + " "); } } int main(int argc, char *argv[]) { int retVal = 0; for (int i = 1; i < argc; ++i) { boost::shared_ptr rmp; try { std::ifstream in(argv[i]); if (!in) { std::cerr << "Can't open file " << argv[i] << std::endl; retVal += 100; continue; } in >> std::noskipws; std::cout << "**********************************" << std::endl; rmp = mime_part::parse_mime(in); } catch (const boost::mime::mime_parsing_error &err) { std::cout << "Caught an error parsing '" << argv[i] << "'" << std::endl; std::cout << " " << err.what() << std::endl; retVal += 10; continue; } catch (const boost::exception &berr) { std::cout << "Caught an boost error parsing '" << argv[i] << "'" << std::endl; // std::cout << " " << berr.what () << std::endl; retVal += 10; continue; } catch (const std::runtime_error &rerr) { std::cout << "Caught an runtime error parsing '" << argv[i] << "'" << std::endl; std::cout << " " << rerr.what() << std::endl; retVal += 10; continue; } DumpStructure(std::cout, argv[i], *rmp, std::string()); } return retVal; } cpp-netlib-0.11.2-final/libs/mime/test/mimeParse.py000077500000000000000000000022051256751517300220700ustar00rootroot00000000000000#!/usr/bin/python # # A python program to compare against the output from "mime-structure" tool. # # Usage: python mimeParse.py # import sys import email def parseOne ( msg, title, prefix ): # if prefix != "": # print msg if title != None: print "%sData from: %s" % ( prefix, title ) print "%sContent-Type: %s" % ( prefix, msg.get_content_type ()) print "%sThere are %d headers" % ( prefix, msg.__len__ ()) payload = msg.get_payload (); if msg.is_multipart (): print "%sThere are %s sub parts" % ( prefix, len ( payload )) for p in payload: parseOne ( p, None, prefix + " " ) else: bodyLen = 0 aBody = "" for p in payload: bodyLen += len (p) aBody += p print "%sThe body is %d bytes long" % ( prefix, bodyLen ) print prefix, if bodyLen < 10: for c in aBody: print ord(c), else: for i in range(0,5): print ord (aBody[i]), print "... ", for i in range(1,6): print ord (aBody[-i]), print '' # _structure ( msg ) def main(): for a in sys.argv[1:]: print "**********************************" parseOne ( email.message_from_file ( open ( a )), a, "" ) main ()cpp-netlib-0.11.2-final/libs/network/000077500000000000000000000000001256751517300173555ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/benchmarks/000077500000000000000000000000001256751517300214725ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/benchmarks/README.rst000066400000000000000000000002101256751517300231520ustar00rootroot00000000000000Here we can collect some statistics about different areas of performance in the :mod:`cpp-netlib`, including run-time and compile-time. cpp-netlib-0.11.2-final/libs/network/build/000077500000000000000000000000001256751517300204545ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/build/CMakeLists.txt000066400000000000000000000005411256751517300232140ustar00rootroot00000000000000include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.45.0 COMPONENTS unit_test_framework system regex thread filesystem ) add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) cpp-netlib-0.11.2-final/libs/network/doc/000077500000000000000000000000001256751517300201225ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/.gitignore000066400000000000000000000000061256751517300221060ustar00rootroot00000000000000_buildcpp-netlib-0.11.2-final/libs/network/doc/Makefile000066400000000000000000000060761256751517300215730ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cpp-netlib.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cpp-netlib.qhc" latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." cpp-netlib-0.11.2-final/libs/network/doc/_ext/000077500000000000000000000000001256751517300210615ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/_ext/adjusts.py000066400000000000000000000006701256751517300231130ustar00rootroot00000000000000from sphinx.writers import html as sphinx_htmlwriter class CppNetlibHTMLTranslator(sphinx_htmlwriter.SmartyPantsHTMLTranslator): """ cpp-netlib-customized HTML transformations of documentation. Based on djangodocs.DjangoHTMLTranslator """ def visit_section(self, node): node['ids'] = map(lambda x: "cpp-netlib-%s" % x, node['ids']) sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node) cpp-netlib-0.11.2-final/libs/network/doc/_static/000077500000000000000000000000001256751517300215505ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/_static/Button-Info-icon.png000066400000000000000000000066531256751517300253620ustar00rootroot00000000000000PNG  IHDR00W rIDATxZ tU%/ yYH@).EZZcuG=񸴵.TE-9UZ(+Z** E( d_eϝKj;w‘k,XƲd)`XYbHCY.fd ۼb~e+Xf9M8e,iHZ6p@p=py;bVк_c fQyq(+ `huS8*DGOzhO}iLJ:/cdv2:,KXҠ2,5,2% ?QN-'w';=QzwoxiW#մt3ukSN޲eH'b,nA 3}}B&1Y0k?ӚJں UNV{טm5P~֯@.60R"⇉$y"+~>7sp U;l_P] {ƣEIK҄aB޶x6c }boc4(S\D|nA;zDz7^]*Pa'TtJ@:3,aD6~_y );URys7N!œA~gNJ5zole;kgY0 1TRM!n"1>6, q2h|S wZ"n9 [^Q+/7rs,dY9Q\L\SPIòHG"InՃ=0A>7?{d|Pч;6P l2z%mc:*ŸѩӠ-O$x0I?N܀3􂭅[Sf, qiÓL G:&dԸ4f贉#?ATdyWVpiA <aV @k-s茑s;,^]\cj۴""> 0|pu ta@vMG~&qfZ A|ܤ1TzBaO>Jdy{mS5Bҵb0"VNMɰSKf\;'[C kIP"RE%[b_v9piaب ha+|P,C]-=,7;LK8چ/1oD8DFfBhd'L7: BD4U-k,Lţ1(Ë*# di@gk6mîD;- #wjNWɧ`&_#wRun18ˇO[@s>yoIJ;0#B 񻑛ڀW-5y>h 2E/MQi~ǝ \~4dylBZtGD!eҨ,7] E;qg$F'obc1r#tFD}{>$p\ƏY*p\2-0RզϠA7E,*2 pj;q;5GQ%Sù)~ e|˯YnۀIZ.eiُS)̐zuYnWh65,qi =^X+ȗ>ʲqndhËOKiӱN'+>kÒ6)Xy#"<{5*uIj\%w QHpAE>Ԩ%fnnM 0i@^t<L,87,N:Ϡ\.ee TTJH:/' uЧ#7RFԑsшPHRhwȩ6jzլuЋ&.), m@!N%95*w\i ]bNe=yeX>5@?,j9+:ŖYqź%x?j!P5s80u8rӽ?YT?jGf7L5Qwis7+v$[uM!3b^~ )MࡄgM7ḍ2c_TNm8hYIDNmv0ǻnT|Ԅ;hbkTeT O=(_~UdS[oSC"( 77 RjH|kp$f]M9[a%e 0U=9(0~sX@mEGp&Ś"59 lD!TBGYNj߰D.k=n{,qVǘ`''0j%. u"z8,lK f~.prB_x<..(2t! F!rxloO%T0H>prDžĖM`+i\F@OD}7ke,o~vglQfe:y$Trl I(ZA,X̛UɯN'#̿A`>yVL4żbG'Y/YBG^{GXIX!6NG>9?\u0BfHl^70L,t5ՇLD\#ӥt G;$빚5|f7'PTo/~,`$yÖ'[YSх$o{c W0;%A^>ar.J C~ -P[bR`AbgT6oˡڅIENDB`cpp-netlib-0.11.2-final/libs/network/doc/_static/Button-Warning-icon.png000066400000000000000000000055371256751517300260740ustar00rootroot00000000000000PNG  IHDR00W &IDATxZ t%%!QPDE!>hEB E9R()b*G7ǩCPXB6 Mf؝,zN7cg,<|K%VGS׌)*`ЩH@51^Wt /:1 9 NJı$0PP!4CY#F0RoDN>-[5F\V$B/F@@㊙Cs˲2[h׼n]C԰/[Ikdƕ_JXk*L." KTL"4Au a\#;# *5y:['\gu_+|N&6:19۞USXe\+FOFdaq=ČLR,@HJ#fb4Qa:9&+zpE kA n qurP$Զ͛x aakK]MYƈqC`MSȣJ&F#h4I/+ wH[爌/+ܖηuhS WN+!@`l9';M|?c +#. fTЗ 4-##!ov-G/<(V1ێ7m)EQ@t yF(HE}s@5*>_C.xxh&ڽp! @JXg8~WXZHzz~ G~6*}dd% F$Rbi ٘2܋0#u b]pOvށa|cȷj%>܊ɹ,!ip-IG MFt-i75@Vې9Donvʷ{C۽te]+>ZrݚRI0!x#@,@vl蓐MH%Np|A`pM a>K."1!³'D!vCCId٘=71{ȌWdY dFpt4VD`>7w_q<@"%$d 56k=>q#<+ct:MPP7 .+}DLI9#Rђ{ti}+4ra=GVB$jJ5QResɣmaďV89a LRm+[N_7"h?`ܓr(썒ɼ"xm Ig!yz%w#pSx/oLj#\xL;=}K{y\ﷰ(qё\yrƻL ?A\̺F"' 5ūa^~9|#x4cu.>X9@VL| ސ*r|Ot &`|C3[ ?.63qaX[aSSfߕcB h!yZM5Fz􉌏t$ 2#Rݷo $ a@k2Rgsd fx T3]K׹N &P 6Št ʽ[C?W\.bfڛ;"qgi|F!iA(Y ̴g dhDOh~%F7 "xQ0l6H5SbIS$ͣP32fGv"KؔB V2ws?bQyT8]"-(\Ś".,VlH< [%k峓 8jB#J!~!l&5:\xWody<+y D=:d20Z"*vfNUX5O$\;4֬aNXjY@3Y'h׍0rf7}c9\Q?<55!֌ks[n ؉N¡J՛fk.c eԺ 2NSg&'B~d߹`vUɍH+~)j?{+~:d`GIENDB`cpp-netlib-0.11.2-final/libs/network/doc/_static/cpp-netlib.css000066400000000000000000000221101256751517300243130ustar00rootroot00000000000000@import url('reset-fonts-grids.css'); html,body { background-repeat: no-repeat; background-position: left top; background-attachment: fixed; background-color: #fa2; } body { font: 12pt sans-serif; color: black; } #custom-doc { width: 80%; *width: 960px; min-width: 960px; max-width: 1240px; margin: auto; text-align: left; padding-top: 16px; margin-top: 0; } #hd { padding: 4px 0 12px 0; } #bd { /*background: #C5D88A;*/ } #ft { color: #C5D88A; font-size: 90%; padding-bottom: 2em; } pre { font-family: Monaco,monospace; font-size: 14px; background: #333; background: -moz-linear-gradient(-90deg,#333,#222 60%); background: -webkit-gradient(linear,0 top,0 bottom,from(#333),to(#222),color-stop(60%,#222)); border-width: 1px 0; margin: 1em 0; padding: .3em .4em; overflow: auto; line-height: 1.3em; color: #CCC; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; padding: 1em; } /*** links ***/ a { text-decoration: none; font-weight: bold } a img { border: none } a: link,a: visited { color: #800000 } #bd a: link,#bd a: visited { color: #800000; text-decoration: underline } #bd #sidebar a: link,#bd #sidebar a: visited { color: #8B4513; text-decoration: none } a: hover { color: #000 } #bd a: hover { background-color: #FF9955; color: black; text-decoration: none } #bd #sidebar a: hover { color: #FF9955; background: none } h2 a,h3 a,h4 a { text-decoration: none !important } a.reference em { /*color: #FF9955;*/ font-style: normal; font-weight: bold; } /*** sidebar ***/ #sidebar div.sphinxsidebarwrapper { font-size: 92%; margin-right: 14px } #sidebar h3,#sidebar h4 { color: #487858; font-size: 125% } #sidebar a { color: #8B4513 } #sidebar ul ul { margin-top: 0; margin-bottom: 0 } #sidebar li { margin-top: 0.2em; margin-bottom: 0.2em; list-style-position: inside; list-style-type: square; } /*** nav ***/ div.nav { margin: 0; font-size: 14px; text-align: right; color: #fff } div.nav a: link,div.nav a: visited { color: white } #hd div.nav { margin-top: -27px } #ft div.nav { margin-bottom: -18px } #hd h1 a { color: #EFFFEF } #global-nav { position: absolute; top: 5px; margin-left: -5px; padding: 7px 0; color: #263E2B } #global-nav a { padding: 0 4px } #global-nav a.about { padding-left: 0 } #global-nav a { color: #fff } /*** content ***/ #yui-main { -moz-border-radius: 3px; -moz-box-shadow: 0 0 9px rgba(0,0,0,0.5); -webkit-border-radius: 3px; -webkit-box-shadow: 0 0 9px rgba(0,0,0,0.5); border-radius: 3px; box-shadow: 0 0 9px rgba(0,0,0,0.5); background: none repeat scroll 0 0 #6ABDFB; } #yui-main div.yui-b { position: relative } #yui-main div.yui-b { background: #FFF; min-height: 330px; color: #164B2B; padding: 0.3em 2em 1em 2em } /*** basic styles ***/ dd { margin-left: 15px } h1,h2,h3,h4 { margin-top: 1em; font-weight: normal } h1 { font-size: 218%; font-weight: bold; margin-top: 0.6em; margin-bottom: .4em; line-height: 1.1em } h2 { font-size: 175%; font-weight: bold; margin-bottom: .6em; line-height: 1.2em; color: #092e20 } h3 { font-size: 150%; font-weight: bold; margin-bottom: .2em; color: #487858 } h4 { font-size: 125%; font-weight: bold; margin-top: 1.5em; margin-bottom: 3px } div.figure { text-align: center } div.figure p.caption { font-size: 1em; margin-top: 0; margin-bottom: 1.5em; color: black } hr { color: #ccc; background-color: #ccc; height: 1px; border: 0 } p,ul,dl { margin-top: .6em; color: #333 } #yui-main div.yui-b img { max-width: 50em; margin-left: auto; margin-right: auto; display: block; margin-top: 10px; margin-bottom: 10px } caption { font-size: 1em; font-weight: bold; margin-top: 0.5em; margin-bottom: 0.5em; margin-left: 2px; text-align: center } blockquote { padding: 0 1em; margin: 1em 0; font: "Times New Roman",serif; color: #234f32 } strong { font-weight: bold } em { font-style: italic } ins { font-weight: bold; text-decoration: none } /*** lists ***/ ol.arabic li { list-style-type: decimal } ul li { font-size: 1em } ol li { margin-bottom: .4em } ul ul { padding-left: 1.2em } ul ul ul { padding-left: 1em } ul.linklist,ul.toc { padding-left: 0 } ul.toc ul { margin-left: .6em } ul.toc ul li { list-style-type: square } ul.toc ul ul li { list-style-type: disc } ul.linklist li,ul.toc li { list-style-type: none } dt { font-weight: bold; margin-top: .5em; font-size: 1em } dd { margin-bottom: .8em } ol.toc { margin-bottom: 2em } ol.toc li { font-size: 125%; padding: .5em; line-height: 1.2em; clear: right } ol.toc li.b { background-color: #E0FFB8 } ol.toc li a: hover { background-color: transparent !important; text-decoration: underline !important } ol.toc span.release-date { color: #487858; float: right; font-size: 85%; padding-right: .5em } ol.toc span.comment-count { font-size: 75%; color: #999 } ul.simple li { list-style-type: disc; margin-left: 2em } /*** tables ***/ table { color: #000; margin-bottom: 1em; width: 100% } table.docutils td p { margin-top: 0; margin-bottom: .5em } table.docutils td,table.docutils th { border-bottom: 1px solid #dfdfdf; padding: 4px 2px } table.docutils thead th { border-bottom: 2px solid #dfdfdf; text-align: left; font-weight: bold; #487858-space: nowrap } table.docutils thead th p { margin: 0; padding: 0 } table.docutils { border-collapse: collapse } /*** code blocks ***/ .literal { #487858-space: nowrap } .literal { color: #234f32 } #sidebar .literal { color: #487858; background: transparent; font-size: 11px } h4 .literal { color: #234f32; font-size: 13px } dt .literal,table .literal { background: none } #bd a.reference { text-decoration: none } #bd a.reference tt.literal { border-bottom: 1px #234f32 dotted } /*** notes & admonitions ***/ .note,.admonition { padding: .8em 1em .8em; margin: 1em 0; background-color: #6ABDFB; -moz-border-radius: 3px; -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.3); -webkit-border-radius: 3px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.3); border-radius: 3px; box-shadow: 0 1px 2px rgba(0,0,0,0.3); } .admonition-title { font-weight: bold; margin-top: 0 !important; margin-bottom: 0 !important } .admonition .last { margin-bottom: 0 !important } .note { padding-left: 85px; background: #6ABDFB url(Button-Info-icon.png) .8em .8em no-repeat } .warning { padding-left: 85px; background: #6ABDFB url(Button-Warning-icon.png) .8em .8em no-repeat } /*** versoinadded/changes ***/ div.versionadded,div.versionchanged { } div.versionadded span.title,div.versionchanged span.title { font-weight: bold } /*** p-links ***/ a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; visibility: hidden } h1: hover > a.headerlink,h2: hover > a.headerlink,h3: hover > a.headerlink,h4: hover > a.headerlink,h5: hover > a.headerlink,h6: hover > a.headerlink,dt: hover > a.headerlink { visibility: visible } /*** index ***/ table.indextable td { text-align: left; vertical-align: top } table.indextable dl,table.indextable dd { margin-top: 0; margin-bottom: 0 } table.indextable tr.pcap { height: 10px } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2 } /*** page-specific overrides ***/ div#contents ul { margin-bottom: 0 } div#contents ul li { margin-bottom: 0 } div#contents ul ul li { margin-top: 0.3em } /*** IE hacks ***/ * pre { } .footer { color: white; } .footer a { color: #333; } img { margin: 10px 0 10px 0; } #index p.rubric { font-size: 150%; font-weight: normal; margin-bottom: .2em; color: #252; } #index div.section dt { font-weight: normal; } #index #cpp-netlib-getting-cpp-netlib, #index #cpp-netlib-boost { background:none repeat scroll 0 0 #6ABDFB; margin: 2em 0 2em 2em; border-radius:6px 6px; -webkit-border-radius:6px; -moz-border-radius:6px 6px; box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); -webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); -moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); overflow:visible; float:right; clear:both; padding:1em; width: 380px; } #index #cpp-netlib-getting-cpp-netlib a { font-weight: bold; font-size: 14px; } #index #cpp-netlib-getting-cpp-netlib h1 { color: #333; } #index #cpp-netlib-getting-cpp-netlib h2 { margin: 0; } #index #cpp-netlib-getting-cpp-netlib strong { font-size: 20px; } tt.py-exc.literal { color: red; } tt.xref span.pre { color: green; } cpp-netlib-0.11.2-final/libs/network/doc/_static/ftp_uri.png000066400000000000000000000617421256751517300237400ustar00rootroot00000000000000PNG  IHDR}^CsRGBbKGD pHYs B(xtIME 58qk IDATx]gXU~iAA`5ػh&1DcL471v5vM` * bwXߏmٜ(3>g6e;kf#"`Ĉ;v,:tPalݺUdk =m/11gϞţG`cc[[[ԭ[VVVoeF]vBJJum1n81ش6mg}7>}Ç-wСC "iM4UQPP 6 -- 5jִƍ///|h׮DbGBzMLL0qD1D[ѣHHH@F0e{mtt4֬Y`899aذah۶m̙3066/>#CBBpiL:ߩ)?3+?ٳѱcG䨥իW_|9>R . ** C )Q š<>Dtt4/^SDGGc֭8yH/DHH/^5ݢE_bذa8x 0f8p@dN#::ѸuΝ+2#'';wƖ-[ЫW/̘1hڴ)ԩSQN5 Wy;ʕ+>|8ӧOYfzݹs0m4899O>XlY٭TR% bƍ4n8zSZ*%&&ھ}իKϏFE=tz0k,Z|9 Lܺu֭)2OxYXXxW?s ӧO5^WPP@ 6͛7q KKK*C*W^huIuYYYԡCꫯڵkH5j(շiХK4jԨTS"o+WbԨQZjgϞرcK|Mi&ᕀ9s`033SĻB {$7'xii٦;wRJx:t(~gmܸ̓ڹsΝ;R;gll ???||oU#}鰵}陞pdgg>{ 7nČ3J}1yRO ?bbbp"QQQ-uy&_JY$''޽{ϝ?Ο'O ,,L㲅Ν;HMM-uy\v O<)uy&ܹSqU<{OBBn޼)%'urssKTv'OСC5Ɲ;wD/ WLL YXJ,Oe}gVVBCCӗ@dd$ U>ۊ.oKKK{표1rHF={h<7}t|~,bccnݺHUV*U"=ZMM8rHrttjժ5kצUV)Ybծ]pСP&Mf͚;ЦMUSдiݝR~SԾTZH䬬,ښ\]]͍hĉsz7((VZEVVVBH~~~7n9::ɓ)22|||ܜիG4f)/BHHSNӻYYY4gyyyy|r^:ժU7nLԶm[ -;ԴiSݻ7ݻwOcÇe(11 DENNNԴiSZhjiȐ!TV-277'///244Fu{daaA^^^E4b5j]~]kZt)ըQԩC-Z5j'-\,X65"igggq=;EMfY&ۓRϞ=)&&F7jժk׮%I :UF4i$LC 5kRƍΎڷoOZwcbbAOgϦvQJÊ+6.]?!!!\_4߉޽K...iONDDz*kРegg];|4ٳ2iyyylٲMfffԶm[ *U_uګh)ϧ|}}̌ԩCd``@&LPW\)]vQ͚5ՕϏBCCnݺL...tرk-[V=z¨};e˖r޽p5oޜ,--I&dggGog\\ <,,,aÆA4n8:s ͙3Gu4{luRݺǔ&MV&[nڵkdnnN...TV-w:tٙ5kFw&MP>}t F۷ŧ =yDu۷siH;v,%$$('NH...v]NNk׎KwUtTׯ':p@VX w͞=HpBENmڴnݺQ~~=C6lɴ~zh|vnn.լY͛G:`@kKjԨݾ}[ZYYQ޽ՄihڴiZ';;ɉ.\O{:(M˖-#[[[k$<}hS@@ժU-ZD񔕕E&LP'NoKqF/ ڷo_dggG~)RvH_ff&M:'((WNQQQGѼyhɅeD:t+GNdee<rrrM6ԯ_?Tu֑:tH,^d 988lZ~=U^Μ9+g.Z:{ш#4]]]ظ}9BdccC{-,͛+%::tB19;;x'S}eJ֮]KNNN{nE|HHuЁ T͛@?/OMM uEc_>7N!>}J~!**//IOOlll͛ggg-4i$R(͛Ww+m߾PFEEQΝi̙ZsrrڦÇ%>|8M:D_I_iĉiرfd``U[ciHfffjK?ӧ ӧTj f͚:Iuޯz쩕uMȔ)S۷1߿_\xx8kdhhu0CV]zLH_XXլYSb#''ڷoOGe~~>lْ/i <ϟ 322Ȉ.]k3gеkhQ Ro̙sp[U.mٲZ§~/Bk333~Ν;QVbߡ(233zj:u%((ZڵÕ+WЬY3A]G:j Jp)_^k *EGg]v BӦMaaa066ҥK5|)oUV:7k gΜAAA?3vލkFRR&LBK_s@`` >2iӡ011%KtwNQFRJhݺ5z*.]`<|PZ5 ++\tqme˖X`A|2={ӧ딩˃w!!!:8::b峮wPϚ,X_zzzž*>(D= '''ֲHHHV*Uk G8r*W\땒b-jʢjw}Wl 7nDV^nX"1VVVHHHx#+L)J?ժUCbbMunnnYf[7(JвeK4j+V@ `ee,DDDvPvm:tz.00'Nombw100 `!$$߰xblذA#;v`ĉR ݋ѣG… jV %e"x<<#̚5 SLHf͚y&ݱ{n\x]vō7K.yei_őbŊ@RRNҷm6L:ӦM×_~ڵkϞ=CHH⳸:-[ eo>\ʪMRSS |r`ԩؿFWV-U\NNua^^F4>|r{9syƍGtڵTǟYҨQ#_Ŧr &OF+A֩%~:֭?%\r|Iwww`РA@VVF67o4h&&&PU*45kD͚51p­֬Ydj LMMѺukn ,M0rHܺuK+ѣ.]}B Xr%F˗/i6lBm6w.o7nЙFy;;;[N:7n޽{QNH{|2}]⧟~*I+ oooܼyرc VZѣG֪!T-XC ?077/|_>1x``ҥؾ};Ν;W{طoƾ ==ƍ޽{yժUѡCoi<״it_e}d&M`mmRkW*4AAAFxxN7uرcիWѫW/s.\Iҳ0p@XXX`Ϟ=R@ s44|.k""">ZO>':tHѨ*FDܿ_Fسgz *SNz*accY455E˖-j*M6+:کS'lڴ IIIZ밶ǏR~;v}0{llիWa󰵵ըy522B pY8q{;vhɎ;0x`}vש"99V?_ ˗?w|ؽ{7ammN:a֭ݻ7Ο?>88u:*7yGƍ5 ֭[K'.1Vq[n_]ϻ6mȑ#љ.44Tl֬tjXr)ob˿^zqVs8 kji& 4H{ptt͛_21tj;LhŊE'N`JKKpZd ?f&&&Z]"00ԩSj9DD^^^%zQ3gPZ4SڵZچԶm[7jH~UeR^b5Z޸q6lH-[hpirttԘ?W\њ?)))#5HIIIe˖iu"m۶߹rb 9>իtYJNN{ѦM^=]@tt4VC:PΝ5^!OOO5ց*Uh]b988h,(( jѢ˜?$___5TF ~>|Ht͜9iӦQagffCZa:t(Xm^5TWK9s搯/O!w===Zݻw͍lll뫶_[^Iu]VUE}ڵiZw}G}ڹٳgvD.ޞ?&###u5۶mU^r\<==iҤIBiiitMZhږ(˖O?:wѣԣG7o\X 4(/&nIiT~}[ёծ "GGG)KC__,+X6lZ;Wh|wƮ]n:?/ܵmk֬)U@*UbҤIظq# ! IDATuggg<~aaa8z(zoV绗;%־}j*|x"Tooo8p@ղeЦM\|zBff&.^̙3͛7/̛s*oootX"E7o3+TZjaԨQhԨ5jGGG 55===4k ԩSaѱcG7Nѣ9r$֮]7n={0c ߏM6 ?~\ǬYСCy;}txzzbȐ!pwwGTTك޽{c̙hܸ1v͛+sEnУGk=B5jX5k .cǎԩ5EZN1ԴiSddd*Tx]:uOOOǐ!C0g]պ^533Ù3g0i$lذAcٳb˫xŰa?el۶ +VDbѢEhݺ5w-[",, 044ڴi} ۶mCxx8fϞ{a̘1 &`ъ)vҥK1ef͚hٲ%._ {{{E7n,4CZZǜ9sЮ];ŵ/O?oooՃ\|w(O?hܸ1OOOddd $$'OD6mp1TVMq;#_~ Zl \r~~~}Cj*{?~Lvv6wMq/",Y & @ժUq%bΝڦ7oތ>}ɓh߾=]???lٲEݻ V իWacc *ⳳ1tPddd~gbb>Xzo#"JKKÕ+Wnմ.ɓxVZi\1p@ < x!rtA_~Z䅇}*wy'NĐ!CʄժU AAAZ+$?~:аaCtUuO> bvZzzz*/^,HhڴifNN.^XHݵ͛qm;EmFHHN8O["##q}qjٳg8|0_|xzz[n%Z|9\rn݂-<<<]" Ш(_5jرcu֧ŋ#==-*u=IMMŖ-[KKKxyym۶R䍷J,&&5j{pDFF"++ رFoiIRR,--o>ǰ;`lV8s uk׮!11 4@ǎ1}BBBCCZQFj{ZåKРAną Dʕ+|rL2M6EJJ 9@i#MWgdddŋhժ o޼ ===eb688m۶UiӧOn:?,Vf}… 󆆆h޼ya!<#9s_}b&M xc۶mj׊+̏[E^>Ģ2AO@@@@@@@ða ow-YhH&}={o-[)*}{`< 5GEm0I_ǎ?+ephdoRS޽[[@eUزӷif k׀;;ܹ'@\'lmWW`&@8L(_~_jKNNC/vѣjՀ7??6zКLbc nnk "L`۶7 />PUÇn4׮ C@ǎS@?|q( TO~*{'[װ!0~<0t(w:6oۏ~=ФIِɶm{{`R[7@[Dӧ<HH֪={de(:x ^@qݻ9s}}]>"7߰mɀ3`CbN- 1Y_Ύ_X[ٳ3gI\u>] DDS&~۶ff%Gv6,LM#OO5k={X/Z|Y<+&@Ё7.B@mD~>p&p4ό<)O`]}<苎f׼9sccQ>@^Q44,8ѣ2- &66Wyp>5jżLd@''U+&cO2z@.U3f-[ 7ofם; 9>p'=s՜ܼ |% WÁfX;:323$9s UGLhO!q%wF$ܜG=\^٩@HS'NpٸrY `Uۛ勽;kT;3N oL@mmY`TyB]Uffmd,J䲶(2!uP۷9kW6mZyr1ׯ֯2V-5jpJgeez46064C m@*LMc9&8O|S zzrh],hFv6kߗÝ;,'%ԨkӺte66^))_k;(aӢ&Eafk\nK@#ǒ%waq;W ~)Peʓ'ֿ?,]Ǽ $իJ呾ʕhb$B^L%"+dfjpLLxJY) _7$6eBmAdKHSKr+=],9Y{r+__A_np[[*ؑZYHr~&:ggٓKMK>z^'<?ɚ\',cXڨQnҧiGEq~iW[[͚yz5W~㏁?׼6*=/1ܼ<>GHJbk8\jP5s4e:KNfY;eb='Oֽ^ø~YNj\ժ{jRRXU؋t 5jp]lؐ5oU!:Ir)b\--Y#&uŊN*ki]UYM0A !wtO] ȗǏ~^O9ËdkW8g2^AJ % } x Wֻ7/"?FN7!DmFj^䮀C\8kSųg+`n K }+Vmϻ@Yzu!f(o+,-|]p(׶N-kݚwdx]PQ/ii̙<D7$})PxwPҞ628w7nׄ>/!<\{ArdǛgdhff&p:_=]J o&!.7.8$Q ]15vR%o;^3rDl@hkL*TT^E #St 4 $`&GqM<5vKUD?pr:v}W-;5W5S?+Ws[4AAo…L ?mYI-[+&k={xWZ׀Wd[P^yw_w8Χ S7n0aM99](o}^t4T@_8)xi[6/{lt< )բ,6oXBBiCAp-Y̘QCDǎ BԳ'ьDk[GjHN&Zh`]>cesnD|B{)! htΝF O4Dc%:h0t11D ;̛Gg>zDD{} QZָvU\ݺ|Y9_>ukeڵD͚=} /…gbB4>ʕ|9ʕ9g:E4s&2w? I3mFԷ/wB4|8]D4`7jDM@t c;;>{׬!jт3{O57hnWD/:Ddkׇf͈:t 5ޞښU3gmҮVƍ!z}.UBC76& _9ԔV%4(+y,/_7ry?Lԫԩ˹r\XI쫯\\y,4KÇD~KT6QӦMdd\і--Yœb gU}Qf.6e/7r_XqT֮}m;D+}2ŋ,7nϏ?Ɔ()I3{Edfus5>>qK &=*WwN]Ǐ5o% WW׷"i'}ݺR~'L$<}(wOO=KK{9$T*\H7}:9"ǝ>- kUHÃ(!AfA ^f=[KH $ھ]y{cb^nH1Yk&aRn;;"77|MLdBKɉ j4h$WIܰ2]j* (sstNRT 7N_,6XO~? 3 ߣ2+"GݿqV)~ }o;\253#ڹSg,{9_չ339./Os~U] ^58~Ϟ/@SV|uLǚ: e=?ViJfX9GgQXW;DwU)i,-w:OD+4AQ%dzg*)P5*``}?篿49vVԉ]?qB]Ϛń#6Vjzŋy` 9_Y:`ڎ*y;Y@I?2X[%($9@n$GG@MKS]|+5kӻE1c۽[4'}s*eEW9ys{egs["?I7{p玬+䁸4҅NRO4JfFG.p'^hc|Iܜ䫢Q#vٷbACCRZԘώ.Uoo`TIu+ EQ]B` w)9~;zxO߾\?xyN) :T tt?_O IDATEUeQյ뢶52zH6Q]>q"Р ~Gf gi٨YN?q"[t{xixxݠm['U1n7mdCXVߴIpHNNڠuA&kB:uʯy\$&*3mu_?';33C׮E;wxv9$ڬ,LL^?OIMݿ_MbE sAoӆ-85It[hY9UBgFf+]:ubO-`HdW/e]ط_?}off|5k=Kɉq-d hoe}؊reSu볡Cym,~ز{6" Q^/ T-U4,K"1&^z!=mUҥK<kg ~ʧn]>~S+5 $mkz|ڵ ?SW/C{1i[̌SBsX(w6o5u\̘iժdy#H 7Q6cb=5ݪՋ2~2kv% XW.dJ3"ꖾ>P\{OC]%2[:-[4o|ܻWȲ3{NwWz} a {rEc@9LMYsJ" a w!!iVY7l,\ͣl&::UWi!]Gz y+`z&0 rZ$͚qF.a4TËˤ[7%۾ce)ۿ_n#~)z5bܼDԴd%i7՞^#hǛ7lu WZS8R .>h?C(Hu\WZ.2SX@giS;; NrI!MZ ]/)V _;cյL˖c6mhS׮& ]qh^8v,p挼qbYGĤ@aK-xtO7ozj՘M$1gEq?3'Gݡpt,lza@v^֜gfCZt Jk$b訙TmέKx`r&~y>;wLثj$|!mS::UMn afс&wo/gM40=UeN۶r( i}Jlƪ+:&;eZrM| ǒ,:3SZP*)>-L$?3))X[[v};[Q*-$VF$GoqG&履眻øqn"}9H8U7Dի&1luDb";~41a75kֻ͛/Eң~}Ӻ5ySαug:t`h {vvzRZR;%ܽ w$ЩS٩pvʃe_?=f`+@FwZLvӵ|nɨ6LJ3TLԱ|yֻnn!",bkD AAА?˶W/oӆff({{UlMl+W}.j1_]RQghV8Im͠AJkdbIJCn l3 u/o>&Ll/==zL ;==)յg/AAr[ӧ}bF16M<~nlݢ#1%~U+,XѶ-mnV뢅VƨA+=}AJж-*s@`iSB<շfSdjqêGcYYk\]YmYtzuH6^*UtMS-Z{E4Uk'[?\ӝ;tB.\ߛ5郲vSPmkJt%'iZV'+;P+ PDD0iT^\\RYG$V O@@@@!}o8W@uMt'$ }%˅,c~q0]ǎ[&vNZ4"?|<oтhC>B H } ' H } ' HC匧O'OzzOU@u@rBN/o(oT,ZԫM^M6{@bzDy \ qjqhDh^6y_2Х 0nе+`` L@@@>rS||HybE͍5r^`m]Z< ;8MU4 54煩)wҕ+˿̀U9XZr<ȿҀt 9<5rkmboM P|!;HH#C11[V@@v6,O%#&5aa@h(0u PJHّJUD7'%XO 5}WP6O@@@>DL##p;#CSiak 01pqa&MG{f\ވ6"'1{{.ZGGG.SCRkGwR<Ogh *( MLx h*TPNxJ3'G>8IREj@Zڷ,,JRA"(WNS{ Px 5:5kLݓ5JM:6m4[f&ߟ en4lȡ^=Dծ*Uތz"@]1UՉ##&wPI@@@@>W$O){pToHf@ B 0J )\z Fh --"Ki-:V6   r r!MϜy$$$̼wwϞ>yd Ҁ[eŢ"Ӯ0r$0|80t\MDDĠ طOY|}]%]ȆT`8'#""}DMڶmwSII,hS>"""" ^EMDDDĠ>""""bGDDDD 3~osvt>gVpDDD-DڴJK%PիϹg0w!$'xQMI!cc=>jN **bNRRddm]]eeR22/8|Xp%yttϗ,-ADĠ(|-0s&DD7m{Kȑ;p4ذX ؿ߳ލ~ Hݴ4ٮ,t l|)$'V|R^\ Яt^|=\<Ͽ=Npvu.]#d, 1#jtw Z+uzK/KH 0xy 'BֻE锠k0 WP \gH G'KZyyͦ[ 'OJm֬/{1[e?zs r/5<  CDD Bbuyegguki14[RiNe<"@۶~==X$\e |b\ZپvϜ9~u_Y 58HIr<._OEDtջtWU%HT\.)Ӓ[Ԣ$4I/"H11}/ݾ5{ٻY4=]IsPHDD .ʕЭ^ ,X<%`O> 05leue<jw-.NKAQ]jV>Pg 1&OW^,]V)&cHHo˒[oE 3DD @uPUoO*p<<~fiJ-{=F1܌.Xo%ωAM3e^n>@e/]Ƹl2Kn.l],\vCZC>ױ_~e:[!sr[@.d*ݗ^q\ESX]xq.U˳ܘ8ٻhʹ-*<'dz|,KDZcݞrrd.e""bGtӆ tbeR7blfvyz,[ItN/Ƙ>]Z”Xcc큾}e W' jyg hg.78Y^\ṭM֎Əs˔-))25{!J7QزEZΟ pZ5٠ArWg;Wdf=sdN )Sd:N'2 3;uB҂phKNf̸.ѽ{Sd=!AxU}88ǁ7ֿs /sm&m?Qk8 s /5J tu3vU}>""" xG(+ơ@V""""1N|+8_\^d$p>Ђ8QU? )v ׿ SR|<%U)I'OJܸ16<00l1kpN'C~\\ݻ;JޡNw""""bGDDDD A1#""""}DDDDĠ1#""""}DDDDĠQ`vf5ǏoAĠ<;W,^̿ Q3C@DHˁ 6V{  9q뗿xYWGĄ(Q#x-gO`(]t6gxew#jbؽKD7-‚f"i$"}DDR}v8ĉ "sk_g͚kHD nY?ÆII1:ii -Y)/)OGl/ep@t40r$e]f&L1F[۳2hFx;%xyiӀ対'e>>ӈ޽TǎJ+uWVTb=z9~Zu}Tʷnc""ٔs|?d~ZTtާ*~?s+ԦMJ+塡Jm,k)ԉJ*թ~e6nen9>m&;xP-9EԈGD{zB0ttۧEDݻ[?ǀ@b䀴%&qq\.Q``}ع8sƳ%p෿WBB"U|$*of>pKZz}on-vsb"*h""M`*tihͽv˖@j!˹|r{?<*Jme~@CVT 2R7pxI`Yw~ڶ5]'uoA$ɑd%苌~ ǧxm4/>IDAT]k\<4```v1[%w:%ӭjFY.z!!_J ʕ@i^ < #"}DDAl:'?_:v nd`T} -ݕÆ#Fn\7J.oaa@޲T8P.Hiɘ7ߔo#HD 7H~gy^gg3Zw wqsWH^\,WVqM1øqJI]`ޏ@PTYgOy=Cݿåul~ ^|~*ۿX Ȑuc ⊴44Zv> xQ֍)^6o.˥ur^k1y2#2̙^}UŹWyJNYwc>gdՋ$~o_KDSlR2p׮JܩTvLfܪR[.L,Rݻ+uRRB_Tnzە+J}RC=Z?TifV*,LʻtQj NRӦˤ))JMTqGߧRoWV*dh:"BszUy ٖԎ]JLLDA#D$Q3SQ!sݺZsshVSdfJkZ߾rwtc̪81i)n ˕+2} gg7XB">""_=A5.;s II<6DArQ݌#wi^_x>""jvRRd|_B\[X|9455K|˗^!999x)`Q2l2cǎHMM-k&&& rVVe< ^T!޽̟?/^?f!/N6 xKu\Zj%>7!!k׮ 燓'O 6`…<۷ocɒ%((([nn.0_;w/+?0uVܺuH͛еkW(++ˬyf\t /_,,,.#ܿgϞ!;;[;PJOPj[ΝùsPhByJ1իZݿ?ñiӦ'P^=$$$T؆5j7oE<=ϟ?x( RSSd q4oޜowիWq91sLܸqݻw1quTROV8 y+BKK Z@nn.о}{ӏ>} 66}E>}0zh=zHV,nS铂2ťKJca̟?Wfy(GDǎye@ ƍqubbbHuaΜ9=z4nܸ7&HNNFաHJJBZ~v9{nĵOQPI?1vXT^D煆Or;vogΜ.֩Sڷo/fM6qx6m7(3%Wd̲Bi }R ɓ'qAaÆppp!3pix9^x$5J⸒=zH?x{@ @ :4hk }+WD^^ڴiӧ̙3ÇΝ;G_T۷3f *UTbBFʕ+[nr=V\'O ::͚5 -[&5Ě5k+++L8Qx,66VB^^`hذضmЏqϞ=T}vܽ{VVV5k 1]vܹs *1j(t/ "u^~~>6oތׯ#$$ZZZ033ɓѵk (ӨQ#\555#22 8ݻcСR"""vZ!66͚5Cl2`AII cǎENsN@II ΰ/u߻w/||| ˓԰j* }13";;Ƙ7oz]ŋ#RSS`{ל9sЪU+׹q㆐oݻwٳ*f>ٳgx-aÆBZN10j(`͸wдiS*%?~ĉ'PƢaÆׯϟ/㕅/^` Dnn.lllogϞXbM6I_|{EHH233ajj^zaLaqF2oD>}зo_899!-- C׮]1uTFFFCTT# O>ʕ+qEi{쑩L:3faÄLzڴiغu+zL)899ɓ'PUUŠAЩS'Ė-[#QgΜANNo5oǎhݺ5z)T8xyyFFF8~8bccq!ԯ_۷˗޷w޸vlقW^ c.^QF!44Ty/_F۶mѰaC}8{,:u+++\v >|8-Z777\p7D'@ggg,YƍÿpXn݂ >}TB1Ʋә8򘞞w۷)S"77oooYnntfnn<<<^m۶ ?^g`c/_,;Ϝ9-ZHaǏ:H3++Kqݻweӧ,99Yκuʕ+%ʶmƦO.Q*LOOnݺez*322bR ̙3KKKYXX͛7y"""T`1{{{6`&eM4a(kժ 8w„ LEE]V}>}jԨ!u,Y'==˥ϟ?3vMV9s&6m+((::v(E׌1κt233屡CSJSVVf111 ķg:::E>יy޷VZlܹQFѣGR@Ϟ=c:::r'OIjb)))2y!}ԱH#qY/gΜaÆ -[{]l޼yА(l1b[lkeee-Z0''')a6m{ ,7upp`G-ux`/VXB&yEfa (ܹ7n,[z=ӧO^z,11QXvI0Auuud R֭[W*3}t*%KKNNfo߾el߾}~f͚۳HV$&Lڶm+b~V*vӦMlE2VZٷ| kРB5jDYRR[6lBBBl eeevTܷ޿MMM$''#&&ժUCrr2%KwiӦo^ׯ#66Y0Qajj*3ɓ'022r[* ###Ce]*d0ʕ+#!!4imۖX۱cC"XYY8y$4>}ӦMSrt޽ëWp%=-Btt4W.l 'O… f<~۷o $b 4ix޽5jH1ˆB׮]QN :zBժUhAQTZ>|({%$$ψ*RNLL,"""J%p^zU5kׯ_o)2 P(N4n~~>RRRpҥ"ϴlRfbccOÖ-[0zh)~u~v-no_~4ڶm KOptt,ѪwŪU+++iii3g\3}t[NbbĈRJ͛QPQQ#G|̙KJ(߇2~'׺>+++ ** HNN.ւJRн{w!55jjj8r͛C]]>>>2chU?JeddgϞƎ ;;;ԪU xe^+##Ca7>E̘J Bnn|BBK WWW gb߾}+vԫzyyĉHKK… 1m4bժU2d$%%ԩS߿?,--0ȵZ[[Ç011Fz ^^^h׮,ᳮ.U͛7i.zC͛7*i @~ac} ejݺu 6Ĝ9sY400P$͛7WåE/^=FUU-Z 2n*U91b7oйsga 6޿/30R])AxEhN:?7nԩSQrR{t8pmڴA5;wԬYǺuJ9}t 6DRR/SQ7o͛EmڵkW̙3>>>B˺TqŽ_~B%[bƍB N8Qs[hXѣѽ{w 2vϋ b}q,1cT"w!W 71112GCCTE貺PQYiii)6 c֬Y7nBkHAAݻ'LQ\|jjj%N77-skmm ___<{ 1Dpp\رcG0Z!Qiׇ&_EЂX/^{_ypuu;c"?9r]N,X yyyE9l~zp"W) ё쐒RSS:u:vȦL"-ȜD@,ۗ`*** 38㧟~b'O,3ÇY׮]K,?gڷo/ՕN:7n"""$ʓ*{LgJPȑ#TZpp0ds-M7(bĈlrdJJ ۼy€H$Ô)SСCb\|pѮ]; 3G2]4(ݻwVZϥ |UgIlll:$NddpGGGY8׏M0AǏLWWWnPʞ={`@-u,..9880 &C a'Or)fbbbccWz-gee;wW^<>|6{R@ӧUVIɫd9 IIIIQFr m6MOOg 6d~RYr٬A͛7l?[LJխ[Wf fbbU㙚TWjj*8p  32j IDATˁ/ё)O8ܺu={VNccgf[n-2(ٙ{J:6mڰ9sHghh(vѣAa1tRfaa!%33M:ݛ5o\f{ hsuvŲ z*ףm۶ptt@ߏw"++ nnn=zTR{{{hjj bbbG13gԩS1m4888._۷oPN;v 3f@f͠ @cҤIؽ{wL\@ 'Oйsg`%\oذTZ[[֙cǎ>}.\ٳg &&&DHHdjժ!88X͇ 3fkZV<(+mڵQFcǎ4h5kD… 󃫫uhƍXz5u___C__7oޠQFܹ3V\)V^'OƠA0n8իWx<==1i$y{쁞N ۷8r233ѥK8qyyy֭2kkkzzzB?7LK.I~%z){I&M6?>PR%Gs>y@+ vahժK.Ç8pԲ#F@TTͱ`X[[CCCAAAXz5tRaϟpuuE߾}%]O>011QXyf9XV'O:gee]"b*U0ev\2Ν;#Fٳ3f pܸqׯ_xOo|IDFF~*W(:txyɓ'1|p}Aƍ#G ,, 2hٲ%F9s ===#Fؿ?(u1a0Q^^ܠ&<ɓ'˜=۾}; ̞=fffD`` GJ3g̰h"nժUË/={gJJ 8RƏlc`ɜNOOG׮]1`XYY ljԨgbȑ8u ###||2_YFVRӧOG.]п(euuuL4 SNEppB?؎;e˖ׯFKKK<}>>>ҥK1uT_^ʒK={VWbƍBu&DYvm 0Ç TTTΝ;ԩSPRRX$Cpss-F GGG4jHp~;wThbY[[cŊ7n0ȏ%.%K`̙x9ǏvvvpttĹs#GJTœꚚ^:1p@={Vn}*VY;vСC Cڵ;vLh**Lٰnٲ¶mиqcn߇(*((@vvЧK9S"""dN7ioF^^BCCQ^= sp"Τ,Y"1$sLKK ǏqYرYYY055)|||d.z" Y R Ο?ooo?nnnPQQA&MУG˖-ۇ'O W ۺusµxB+V ''GM,Y"U8$%%E cRSڨyŁ+UZСe*sE6mp5;wnnnͅ.tݻw666݅+u rp,^'NDڵaaas:::铔 xW(p .`ݺuPWWGӦM1tP :T/_>q$%%fff|L;v@޽e'OƖ-[PNt޽Hl?^ ²E {n=zY&LMMѥK8pXӣFK%>|l)0YrѢE|Xhъ˗cΜ9R ,--o>t ǎӇ.]7oׯSSS̟?By[ը$dرŎ;paGAvpilGG!40cP>m s_y%@Tol,ҥ!(=N Z>Re__Gb"/呋U)So[BA0lf e``hؾ}c*ZxϽacի3Цٌ={xݺጩPFy{+>7 1 ߭c|{hbŅ1%%͛ƺta,!o"޾eʊ^ɿܹtC|[r']`IòCT?ʕxb>Zc۷3ּH(26}: y+OJlޞ3gO2fnNVҥb# -]kDdD8uח1}}c.Fyodg3vcudvXXɯǘ]_{nW??,,=~]fyh.^֮ƌWo!nh4n ԬY:r|<  hj <<=i`  nn||9ԫjl ְ!Pݤ ;7;[qsrhjW ߌMM@jU*+nṹN&ͥǵ׆ʀ VSթM54dVRvqq@l,C۫Wӧ".[&Х е+ЭҴu+S'W/য়--o}\ JTD"1z~Mo/>%1p2t!cDr20{6p(}Eٙx:%>NoND:Tʥnnć~ g [6 W|OX\T'3QC䆥K'ꃥEj*G"]G + R5Hg6ѦMN2-.m% (]Od@ ȑqTlmI8T&j0n$%-,q)3-HQk@3DEw6 pw)8L[D PQj&]jUq+**)'hsFDk:uHӣaCL6)mwČ%o|*ʕM8Z\ #6NI6yEC03ih۶쾫@x{Sow]]Rl[ -n`U)[v61}Y7(h^=@_xQ[}m=#CDd$?|h*C LI-ZZ[*ܦJS-?&~-_UV6| ĐrBed03ؘx7VYa̤kDt&;+K4L)tNԭKƒƍi30- #QQ^bbH~ AvOKu_ܦBʵ]Z0Ps[Z=o: Snٴӧ^ڹJWTU7(۷>>D_jjرW ;pF_UFQ{C>u+TXl Z33I<{F>2R%$gyА195o/^Hn/_GVp4FF 3Yj3KK2L͚}5?'Oh`ZqJ_ٳ/߾ = \@ʕɒlaoO3#}u##0megz׏fs_zt2//=Zh֌CwwS`sh-(NFN"UN#S[ѣ(,,hH߽=7'A!=Dt41Hn\D>~nZ"K;^[YYdhԘJ/9hGQI 01!amffrOH'O9IޓԬI5*%nEKܭ@waqy{xJn]Iw" g )4/^-朥0MKѻ A(ZMsi!VNtY8䬂 $_kGWyP`44QadDggAAp߼I0(sagq_gkO/$&wIH Mr{IQέC|zV&~eg3qJf'F\ znݚ(DŁ@ ψ_p)qq?<Oᦗ:uD^=LNx8)0>r>}јx|/,>^x_ح뫜?:)"II%'?}JeK`Lן>q!mֲ%}ǚ5E/ $"'j'nYԭK|ؘE * 8!!ChgNir%Whр<~L￉Q^GJ/)nT|&Ngc"ڵi[7 k<*Itn`@ӈBǽ ,:ñcICe(x'*k׊ SSr.FFO(?Ə'7ir8P -@_h%y(ΦWWZkie%vtXw ͠%%Q俦&Ygǎ<*6 (Xh24ٳO3+V"Gٻw~1] =΃GEDJ sf*WiGKKmxIII/_pKӼB˃<5>~ibE4b/ ?NƎ͛ 0z4ТI2g`xv>]34,`zShY{uqwa/Q6ϙ^ܳ)+"/8h03bbժ@Wiiŋ$ڶ%"Www`gr'kTȯ6$dAw/C ʷtx}y³gV޽$iiQ8xq0IKJb,:eز1ss<`gVzCJ[w`lR:vdޞ1eeƴA~BcNNtߗ/z1*Ub)s"cuewoק2ۻ1SS'W^&~{ bG;v,QJպ5c֌2ֿ?cϞuد>ʻwguщ#OTcGWgl0231OOF 21󓬗tmGG22w5hٳTǘ虝ۿɽĉz%G\ܱ<*>~$U};rDDcj_ǝ;ծ̙]ظqTw`Y{CTnbBΎx:w_oop4d++}[&M׌͙#5OuscgO*0Aڙ͝K[[ƍ[QW[LJ俙GK'Û7M,:}j ֥>Ӯ]rsm.3v2c-[2֢cto3mI}ϓ'[Iݵ+c^^k]XTG B:'/\۷<;330;W}5uD?+VHʝ/ !7r$oْsDuIsƆmj!aTQ\ J*7o2X@,;; RZ33j,sRKC'76cUL#G :wΝܸA?{:x'JK 0vRSE 0ְ!};T^ibBΜ)>E_ 5DwnnYZRҥ8Le))ԡ54H4@҅yQ5mJԩ4D mn.= Ty3b殮e)ћ[7/fO*^]D$8t.OJB @ccHa>Li muϝ)ʇ2)RJ +܇5)**ʛ5# =##En8'DEw,FkAAJB˘yr -]]*OO,69Ĉ:8mrWS#TbzHFaapppTh9̞MH+\50[G75/߉\ƪTaS'k .%QhuuJ۶1NV2q<.[]JB )dGN ~ȁ38:"u׬~}߹#}m[:@LZ T|Bk*72m0=Z*WW'WOѰsgc;##1UU󦨼qc/጑B 0vuʐa9HXZѣ@` q#EU/MV>\ڟadF:ĭ[ÇgΔvԤ}a? ##8 W(1}A9Fl߮mƼTyBÆ_%۴!ssm)%г连$$HmH4gi)y>=y ki Ӈ~H[r%%J9ֻ7-tһػwNi M[ ͚Q“'TF>{&OvhiIL֩C0>x+ϟ)E/axZchT5kR)EܷtB Щ%K ̟/ϧW䅝8p!QwoӆС6%=-.N9c{.,ZKq5UPl8(W/ݘɸ)no]͇^[ϛ'xڪp@U]B"BCIh[YGMPpQcORyHYYWv_- ~**9_BAQYn:u(1-:dp0u<}}:~XTV@M:%A^Ĵnޤ6ЁiiɣCRh9^)%qR| )0,)))|WDSE ؋\HG)76i 8A`8*?"BѻP ;@Yyygΐ"[XOӣ}\./;) HˡvmڧIN7h $Ɯ\ "zv:;o>$m#Ȳ5-'Ν$ihoR%Ieˉ#>Ǭ?|l)Bi"|ŋ"߷4:8D[[T-`aA`_† <uxFd+{PYtbEr}nZ"(G8;;29#{ ҡe3Tj9n/5oYv}<]{2jhti@YhSSEY3QzHO'XpV`y\_Myy Im@#ҩS_wΥ'sGZo<ϠAD.Q߽t;!J\`mMS'N7s׹>(˯Sҙ-i6kׯIgܷHOw}f*6UU\/ԡ6}f\]]..B%ϊȥKrӹ듏̞MKcRɑUIF4HWbƎtE(ݺ$srrX-o8v صrsq MM0W@ dOr~`_**{j?:Ca`]iXYɾ qc߻';',prR|EqVq|S-I*)\\hv-S9TV"tb2rOܽK[Kд)%ia<{V櫡l6Ijikw4hn7,L e%v$&LLD,[F7Ӳ!̝+hLO~SYb|9}d''܎3 $YLAGOJ 畻> zY S:5k#GwPVPݻQ3r$19C.~o p ŕӣG)˜ٳ\p0r!2R6-qd8}[g^Rϩaf:֤ ɰTv-1('7>>s&} ҭbK:K''Ow[WFe_5kR=n²k0E \ƍC 7Isq$r zEu ʇ&θIA.eeQs޿O/zth?&,랟>1!]%{?.G@@9d54D ߼!E eQ<۷@)5:-~p떨;`+Utww h`tN;G1DxTxϢET.Ke7ǣ*WƍqpyK|)=g12!:^6%00\ȩ2pW/_4 EQ&JK\]DTtr,8 NR:%O(*. A(Vu8\_F6?(y/{;oe{Mibc,X[ߌc X|ΪJ$ssLqB?nrE$qHWwߝiHAtIj/Yϣt&jQK;bJ(Y9ss9սFE4 *z{AA>,U݅B8XZkkI)?Pptvl ]@܏?ueZz|L4=ߩn3udD5~3}[h`:l-|~%*dx7Y/ ۆP5ň}h1xM$tqwIg_KAdTJAF4 ]j3g~$B*kju^v[yMIL?ilVi4L릳}2Kl !&06KiȑVklBu`Uѣ4nܸ&} ??_w)(( [[[JJJRȠvڑT*%D'N @^;''&T*T*}1cp!ދy/直C+WD|*B*N7,**BZZ+ևx׬,<~AfffSdff괆>|ؠksrr[QQQ2e0$&&e47(?D"AJJ bq)--œ'OƏ?FQQ?뜗EII &>c}Jz#FH$7ĉ‚iTQQA&M" kתf:tM6dnnNvvvdddDs̡Ó!H$won2ѠAH$5988(=W$Qnݴ hʔ)ԢE j׮YZZ3EFF=i4`ĉ򎂫zX,y摭-9:: 9::Қ5kZ(77֯_OdooO奢 $HDHz͛-iӆ֯_$۪*Zjuޝޞ|||hΝ?~L&M"KKKy^Ў;>͛GvvvHԲeK #XLFS_yy9_e˖ZFw"ڲer֣G$OOO 䐯-X@8={6D"211!'''%~JSH$UVٳ̌,--> TJaaadnnNZRz^zz:uޝD"͚5d2\:wLԪU+KjLQPXXR^Ѽy"h|l߾=YXXаa(11ƏCQNܜܜFMJ޽+oW7$[[[hJKK#///:ӧ"++}ӣwy)''ZnMBO>rrr ]b8pI&w}FJRJMM$JJJ"HD.]j2IIII4eZx{.I$&&&#-]TIQ>}h/rvvKNNVyǤ$200J䐫+ciԨQGiȑt]ym6k)<<Ɔ:D$J̙3raјH$ ÇӃ)))@˖-(/_Nr۷o?;Vm^>z􈜜(<<pС'OC4e:y$?^@8u988ЦM<>>J#GTW^%'''Zl(%%%͘1C/qFt\Ν;ZˣO?hTZZJAHTXXHJB޽{cݻ7Qpp0+ ÷~<<RС>QQQC(88P@1b^ZcxhhRY0vXqذa5k֐;wN%_%OOF\V@1`S$XiR>d2Z|i߾|4j(su!//5 TJqF.]GLqРA4o޼Z;0[oܸL_SN6m;-Z(A&Q@@։%_~%;QlDD{~j[nTQQ3gΐ6F$Ѻu:vHk֬Qܹ3)``` W%YZZo߾חKآE j &M6\GGvªU w"::lwt233xbq6l؀C!//Om͛]`ԨQxo߾*GuuuϣGb˖-c۶mjXGAv;7bXbR^^v ٘7ow裏Zh={`ٳwݺu+V^6͛QRR!C~-ttt(((PSSS6gϞJ~|wyf?~QNLL 0gq>cɶS|0bҥػwƵA߿?vڥ6tPs 8Pɯf7MOO_|+W ##հWk׮aZj st1^Ѿ}&}~AWW2SSS*FhPաUilttte͘[UU{{{q\]].NK^:88)))ر# 66FFF׿f͚!11ܹsӧ{B*L"B^^lmmUlmmqY :ׯ̙3v8t222PXX333m%%%еkWi D"AFFZn\ϊajjjDK~~>뜗@d011&MWWWޯD"XC AJJ Fӭe2,,,j}%KWUUΌ+..F߾}Ѻuk|ҥ lll k6IecEEEF5ҵ.y9yd4ʪSTW^Ҿs "„ W_!$$DEj O!h#>>/]V!..% ZH$$''D:eBBR^zzzb ??2 ֭bbbm69rφ< z@ff& `ĉ DXX;e`ccv$yz]M6+++(ud޽ϕs R?ѣG98xzz>{>´BWWӦM[}zzzJ>aÆgǎpss88pV^G5۷/.\;ubqUSlݺ*؟U]yzzՙ lڴ UUU*ÇǾ}m۶K3DdCZZ ֭Ñ#GG<88GUi"--  %K SSSEZZBCCժ^Q"ɐ$y3f3UUU!$$y<O>m˵kװd?^kL:Um:s?>EEE۷/ 0@c ܹ , Ԇ۷"Hei&l߾{Q+@&NQFUFӦMß ===<|P8pYYYؾ}Z?lݺ#GT\|8|0fΜS @f0#ܹstIII?>~o}JR4##bXl޼9~'S."##メCm۶x],\P嚅 BOO=z4QXX .jFkc1n8TUUa1b<==QYY\|;w5۷o?b?Xr"551bV^-W̞=w!&&6mB۶mҮ[xh"Y IH}!88 BϞ=!_!%%?~<>#a˖-r#Eݻc̘1pssCaa!O<|ǏMu~ hӦ ЪU+"...][o\;w\`*777666j'̝;fffӧ www )) 111Ś5kކ vZc׮]HMM0m4b={IIIؿpzjoưaP]]+WիG޽g\p-€Gɓꨓ'Obܸq8xźuHXr%j BCCF7n@zz҈W^ϔcvvvvJy` >\_FDJm&Uݻ1ydt =z􀹹9p%?2ј2e 8 8z(f̘e˖߿aaaHKKÇ~̘1CiӦa̙*~:n"axnmm-f?|߇ܠRRRpQdff">bcc!abbI$Ԛ*zZ (͛7pTGڵkDǎѹsgiեٳ[osѕػw/w>}#11͛7H$B߾}ѲeKy OOOΝ;ru&/x7|u~OFDDN:Uz pʕZտ[heff&\]]&B 4HIYYN8x>>>ݻR)N8[n!//]tA~йsg):::puuw_tA˲nܸqFÇybcC3f2Pi|yZl߾ up;Ÿy|1WYYqtp^6۷}2S%㈈  |֩ΫBVVOb>|8>c@\ p8E˓p8\ p8 (~Qy9PUaaG UUӧ[O[Qep8Ơ50B,,͛y՗rwo@$lR+b1'`iɜ9:Բp4r:{@0H&zndA÷g8jmxQ``Ԇ+&NСks8Mϳv)juu=Y;5cein.>x|!19`| oը@t4/L8*^^@nlTҾ=ULDEp>pڡ7ě}AA@` k?j}Ba!ʆzԭ).eǒ_lmh]䔔 cȈ% S-[ Pˇwqiys C4 @l,p*;^Ƴ6mXtVVL%hnΜɋ/UUI$XY|Dtɴ2,m5S=*үy-F2V˙\5RZoY?_##v6EiUkCY99 X5'DgBj*sa`6km`d 'TZuՊ[{"_B::66ʿY9Rt= NhX#VM^JA2ϺCWWj TThyX^h]ꮮ.ks@ סC:#169LϥmC{kS``SOdf2iٝD,mKX $'dd0'Qry۶@vnO -./w2[Cm=ccEO C7k$fn.+d. 맪ZI$,cUU)F/½ssfaeT0̶ҧ*+#M C~ j?[{r5vnhWOJX8t,(P =+b%%lIBSy&'cf06fe`جKgGf:<>Yա:^QW\y:gmB7޷d2֨_U`ƬanIV>]f<|z^IL TZ(pR7_7$UT(t5P6g`}WVUYYL\z:S h^V_gXvLNVld:R5ݫI"QϪ8ksBYƯlr:JKY|fd=((dXc~2ppkttX-`f4|M1LytT_{&WON&XG5^U"+ڶJenͮU5`XGhQl3 ?%=O^ g{{{(`IDATf~>lcxnG;t`ᕕl_?f&Īvس Օ "KK7yI ч*&$ZH&#JBC+zx0S'ZhhסQEr]z&x=KdbBdhH֬Qߟh&`kaDDC͛G4f >ѥKϼq͍a"C.]}8WD;GtQ˖D`k.^dOyi)o[2?()7($'%:ID4t( ;rhH Ne~DOy @ 23#T=yBԪr`"__e7YAk֌LU +U ,͙g)ӧ1e% ʅ~j?oO&ceg?6oNTPK;ʒ+{լu oيӦ1WƍSwd$_H@9P?a߽kn=lh9g&`{~JҩH>v<35Uo휛BU#a{3u5 .ņ9ȑ{}i"Lq--Mw4۩N2ͪ-.hZ~؋xx`|g"~` 0t(fdž)׿um*uv`6:UY @6Wgذ [חW=m3/)W?p\lL5,4b ;[QOdSG8aa bmZ8 uzÓ&Վӧbc{S‚wYŘ0ut'u9q8LPЙd{VǎLuuGj`Yc}Y?5ig*a0:hL o)++v%&z/~~<8/@ 15!b ӧ,Noӯ?ˁ Q_{X>|lqSGuYH3;XTW99@۶ Ҙ1'ʕ#au 8&Wg(۷gFb`7d"` B|лOhdY8YqNf|/7 =z:uDݽ5UYELNfk$aVRy~ԍcbXZŬ,J$e? B$7W/TGA0@q.v bGss`Za6hlߟJaDgm3rr~dz8R)}ѥ 3hw LWaL0?&hj6mO?eQpqa>NcT|9A׏ ._f+Yxz:n]\Y V^a!^aq^`yn 9-@ڷgA&#ڰ->y=GMMoyIH`e];^: 9X٬w߱2FG4kbD5 | e͍hzm*"{{olj:Dk4 3]Rz3b1 󨟥cuu I?yܾS:MME{L781HLd\??6BHLdt77eKץ0ۂ!;d#mudg454@/ SyhpFF'OxZp@p^KR`6,%6C; IENDB`cpp-netlib-0.11.2-final/libs/network/doc/_static/orange-background.jpg000066400000000000000000010521121256751517300256440ustar00rootroot00000000000000JFIFHHCreated with The GIMPC   C H !1AQ"aq2#B R3$br%4CS&cs F !1A"Qaq2#BR$3 br%C4&5S ?Numosd4q_,#;/{;)[?۽\mR8 OzS[*Qn;T] .uHwDs&p^[jӤ%m#=T+j7[`7p>$ T8Zsd a< <Yq9JT<-nܬXҧTVmCMBnPs$vMiZ k!29Qb"Х!_0N=M?OmD D_ e)Fps_jυK嶺HN x *jz' /3='iw@|VCy*ˑkm扶\Ƈe-=D sV8ϵAV63'ͥ*RJ靔8%| &I Ksd0&vChemJ ̄gRӗPpMk{J\}mJ sS'iKxYI\)4X !%x-y؜QÁiR)ڀU8]-p"`x-IwCVqE 6HC4R5Rf|nW ZҶW6q3r7=HVY?[)K sV}Cp17kX7%LZɓ.6i)!lEU:~׻/\Įx ef:n:[O~*q::`N2%m/$`}<3We5IXɗpUZJ$4GH “p=aQW/>OR\"ʝn Aa]'-:^ԋHӯ2K֠J3~@qw\[wJ[8WCdcua)L~>(Oiu]OS/m51Ԉj{Qo~d_**dgI!%t+xkBU FBi! ;8NF(Kmm)*IPGN"璢JDp;z0{zTU%#nUNT[$%^)hY4%:Hq7i^l JRQXuak+~ 2r3K x[:k<'04ry$)'=g_\%o $XcnOJ^av#[RCh('lCϺ=*#QŴvdE%{F}k-(Ï}b&6z6Nn|u?zhcZ}JVl-:.1nji,-iiH\k=woM!m~c*ق<`V [2:P=]eAn[%3# ںk|Jh=L:Txu(x'WQt']8) :ˢ΢հĻC-GypqcRI]F6dH85z :7bg+uh󭲞s\=#nbBt"٫mӘzR(ޫu5`*peL;?GStJ&[HAzu[++mՏW <{lyp@wƕ%H%*"x h^"""""""""""""""""""""""""""""""""""""/׶WMwv.4܉.m:pT`5 _}e#^#;߅8˭RSbU:T]vVp_*Ŭ8-qMw *0[YmӦ"5m6 ;UԽ`' u[PdᣒWG,[lMťa$6R~Ag6)_ -{N;};h㙢HZ{2J\-$)~SFwVj\I|D%ccԄF=1RNz{'+ Rn-UHv"'WnQzf S{-á#d*ٖ)0ADv'U+14~Fjm㿬Ƣ);a {":p;F{qU٬2S 4W{N0 N;{֣APu@1VQ"uTܤ@Ϗzsp9n+a :Y]qS'.XJPT$3*w}}Sdd[m/z~(}􄈦 $i{W H>=xl).$utoP \NÚ녿I*|i 3H]Uӗ/2$%V8TA*F] Z;}D-+Srʶ k!QxNl9@MM=\:ۤZm{r{z\O*&ɒ `rxFbg>c;h9r zu !0 G?_j`(8j^eu \Twb }AWїoJYڀJ5Od`} wPnT t5'nܜ9ʕkXxײG&-?6Rʤ/RԐ ijf=˕ފXSWG=I$T1H/j)Mj%<)"x}*rlJF0mjUvծRR[6y%O ^&LwN0 sS9%7rFGiF#4MTjy_)$Oi%6BV^W 9^)$SrdMN,K^^WVn9DvPWKoeyn"Jn-T#:OeZbէu]IyN˅l 'O[$wz6)j kKu_dCc^)'*aYuʏa8WTeYTdzGԉ&>z屸o - UTOIiLF)טR4ʍH|Ҷ%'0Tt"a讘uI菰y@d;uZFصR +Ij{\*9Ӭ,$CGI/h]tv.y[B*"+@>wB(i}.%M ~5Uz-# cHssr?WPɌ5o꧀Gϯ3_JФS߃O/\F g]Ncy x6]-]NpxQ6)<|I&%[tMC %rb(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(Bi?=3[x#_Klݒ IJ.W77w1l@#a•t|9Z q2F2PϷڧW[g@3DrTʺgR2eiC˸.26Hj7˥Su2>cjEN!aZ+m6믗r?H Jqֲa>:q1i* '8h]h@ۻTAPȥfBBZV”N2|ʶmc#6R*J[ R=,ZY~%`إ;$ޫw;,r8NʖᐕSLӀce'T(*"v` K+)JN{2 ѭ:ylSg Io86%8*'ɧN07@>'K$2!-Gג]B5UXY2hNv[0s+jVE>bAKdN8~h fx۟VNLnR <=d|%il$Z(.v v^nR J/yM9dKG%HlN+p7M9Hr-7'ژ=1}E=V0p ՜p 3dlqiHyXR9Hp^s Wllr>QWL㍓ܷ!;o אDKSatG`ƕ}B>kh=Ѡc8]Ӯb9h!|xr`%%Cc{O<CƎ3.TȞ|րI89<֝]GS!\n˜)%.%\>=ꄖǺcd׾R(Amzo|Q*kԽ(/luuN6JBc9._yt8p ]CLY.©_=&+S8V*>㻈ʑ?%Ȋ}LԟcTKG?CrZX#V@#Q. z]\_‡1JG#t[-oat??En1Hi-U4dʎFdQZ<}?gV)+burN=_[P̯#E}q.$'G)a>8pPXjoqR3lچ=3G5 0R1-m#5!Zئݔ~Ap7L&9N;&&@#ړ- b8*k*Rr;YTXDrŨVv A9R7Ψ Du=>oNJS,?JqYhhGt<.+V] w{= 4DTᬨ|eT\u%@ +:y{+6F7)JJT*J%\΄ !̨{)sz[ynm{ڍe%/ wȄzyVƬ6xR1HʿrklWV[m}iҝzafbC8Z:m1 ڦpuF)6If#* sdm_SLpi0rSIfk'1ҫU÷KS3-BTvq'+ZjZ6UӉ /#6iXK,ő?{*kB+j$OZ}Zw^KJ doT(RF5ݜtvlmA%qœAJc5Yo w$*H9 H !GޔJ3R9*RA.̅k9皐 rJ=9R<~l֗ y8[u$hr_ov3#ޡԮ} qxfrC06'eM {eGoZ궏M\ w'}@*Nʜ;x5ohWI1f4 PF|xTs2\|dWѾ-{c5qdΝob88 Mu &ď);r޾- !܌ll9 q ZFF =Z*=qcU!ԩsb׫EkmXAqRz}M>TެYPn뢺? 8_NKi6ƞ6J35<_#-Vzkhpp ?uzQCuF+Nv/P[Y]Nw#qW|3髓Z~=Q{Z!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~b3KE|J/rprM<ьǜ"%N|X5H9'mٷ9$޽EZuZͿ9w;_gI[MaSA($8VFr茩-dQJ:ku dD7RjZ9KYV$~X~$Ä8JR9i#d;c8 ov 5 d2T'#)_Mt%E(R 6-lٕ 4p+GKn;{5CƳp Z h  JJyׅ=nd0}ÒkH Y/y!}DeG422Nc=K6+N 3D \BPҶF`f'[Ϥ:D8Z͊na];Ham:{sk=2p!ݓ˖/a =^J]*2VڊͳtaIXN?H=cڦ;[.J'aln!CϵR9vu}<4oʃ5+@jp,B5WOHjԭCc ƲbwCc_*}u7}!sɗCc >V mj*Â? \Κts8VnV~rӌ:Lh͢kPk{6;T/=5,UlK@ ߢ\n7}\1+)Bkz✶ŲipA#;7QtuP9VU|L\.k7M?!fOu( ސZRWX rk)_쬛u,an{Ƿ]$GKUq5'!\;O0d2o>g04Euգnß;׶_ToK Eweb8#N[=#9N6qJ5:g҈md%Gh- )DcuoYZ,Sui[Z!@IOPG = 2!Vt1zH9ZfYԹɨJ ;NkPgpmNmDZ 7.*:Jm3uM9A@䶂V*]QQ-(.:^U5.FySAξU I=[` VV5Lt-դ`ޣ+'TelWB[u*4[ZUsE*E]\u8ޢ9sMEXYRQ+_:a|*kkm#*=+{}>72"&o$ {q$C+2JvkFU})] 8Ig?}w/m?%/ݵhn>g62x|Һ|;C_Ӛ:B6'xHW2z^sp (h퍭A%}"~Ʌ)GEWqCE}ttC>Kp>+1`0ll$Ev\Ln0;{j\k'>|Ewe8e+9V_4䣷tts:J0HL?,stfif\˃ᰐ& ީoLl>Ӛn7ًK'lT$%v=Lc]VMF3 1\?N9j1 pU+89n.*le4pA‡|3wgZv'WGP6 CRkL;vBP 䊐QJj4V"YfD@Ws]1>(L hiX?֗{3j^]&[/mGg\ 21MR +R7ae!cMM.V!n% $p+ß N=I說:L5z[$VluUy.-=SZ; <Pw{[=譒gج4z3zSIFI @JOޮ;=ׇ;IϺgx#+51.vI޴='8)>ƬIӴtt}T)*$&9}V\D@wwW4qW6a.} d@Cv;%1.IfHQ͸ڌkcJIM[kp=Uِs+:y[6ys\=ծǝk ڒA{9]O?G鞉<+*?k]?p cc%oGZSPn}} RTn*3Ǐ K39-+KuγfZ19ۭ8(P8 jjK\2_V'u<-{N)LQBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBqe+FGrӌ8MjCLW0wsOr驂7)'8aќˏuFJwZ V ,l$$fGVe@u"i[.8}Xnin\vR }a /`fUe3[\JI_j6j+x*٦Mގw`3Q*Wg̥.oc D/E)Rn<$N{?Yd8-vۓ/- NJxv0&ZQ'+޴8M}_9> m 2"R4˲S'7lDTTԠs}L!UbKےZq5z*c|{jpp S23G8+xڨ%яH7U-- )ʔmk/b= TՅؓ'\iϛHQ +VSQTE[*J *CCK{c `lbjyv+YI$$d* 8ȥEewjXMNuv#Ԃ()Pgx5l~.IcKwfUê3vh>۳tڥ];\.,6[uqʚ)+ZNN>uRY7w4E^گiۄxQ_X-gȩޔ5 VyZsnO}8N0nܟe_F]cf#:74܏cgڙ"s}1ّ+٩n(m.4PWmMg>w^f ԋ/&( Q$doXʂwH1۫b<.0CyUutԅBCBmYJP$ڸ [swL)^ %n* 0nVq#T5tT JaudSv~IY9CQӀk:K[uk;-ce}ystPrWxRR(`{>[2H?Ol[-J|4wӚɦhz{$NTgUJ'uLm$!'!|~ks]|yt-<T(&$.WNsRi*%ড়\G%εN=ڶKSiKsÈ78H8}lum[)ˈ أs+ޚ鞀X= 3)XSt}5˞frXN\w;:a%]kE_f"X<~xd_;{v+z s9Ym_aimQ; "Ճ|ځ6/Pwq՟lJ&+^1|2p)+;}I[3,0oIV?i+t.q>R HM7'TO@~o^iIdY\=ivjG$-60A@+fytiN6IQЮQjSnl'ԝ/{l <oGo'm[1TpA?dum=9?⟵nb?|^ ܫ""""""""""""""""""""""""""""""""""/ge)( E|:J#I;^r6#+IJ+6=##de3 Aq?Iґ׻8+/)V) _ɨk!>H¼v*pv{UvB]_BIqd5%Iѩu g&zZzK|93$T>C~3rH粂 84|+JoZA^`?T?z>Jث1 C=-*y\Kc%)'>I{g;Lc.ttRtn-Ā\P=N)N6.ga 7<ƢrwehlS28[5Sv8V9 gPrlhJ}jRc Fy;S@%xRn H=)Y퓩#hH›0 Rl'KwJbF{׎9(N!^u$e-r}FYbc5' ݌䆥WYŃMUM~+XxUtO[#(ݜӆ;<ogH&B+xq܏Zt.XuԒFxѐ›`[Cw.ֳ{B 8=~ǸuufF7;]~kfs OcUTyGj2, 6 PHNwY$ =@Zaڃ]fח ѓIN(a)!I2y#K=HQ@8i" edv6AFҖd)2R 2(^8ȬeKc:{ sQf錭 |w4MI@Lsб?4Ntu`(ԋZ9 9VM=W>C B 5|+kuy8Tc]F zw~g}Z:j[PՕ,=azF>Mqwߊ2Ei7Pap1sCwVae5Xܭ`IiWUΤȩy>vR/RInB5P[eʏ a[:JgnƐZWV7710G|?USܧ$SKuOcNɻ=ߕ) ݀+R7kerdi$19 D Lˇ% Ϻ86#i{ed7j+^T+=7kn'MuiESUvSˁ\슠vw5 I6=.dⴧPth?U}\%kѥ!Q ETXS3R0b궧岲9@NyZ}v. a mL;!1`Ƹ*CwXQuTr?IU^D"*Cz;.hFM3%nFo}hǶ;j,B!)A]UmHojբD(3T7@T՗rlF$n/r4ʿE'y֚j ݄7aZTje[&l^[U|pr_jcS7#t^f3@Nh(s(;N;+Oj9 [ %Nlgon7?TKĕ6- Y/B#ƚfO*)yܜ˭;/5v+KGx :U9%Me!DU&9gOo/4U:rӱوSO8Ѿ3,L:guVte=k߭5vvȅoWġX?<зޡy h(:#Sd.JqK&dyڐ026XGb:jхoXut .43OT3 !mlv{Rr[l+m{=m]C<ߖ%wUpVּb)N:\4, -*W$7g5 ;WxVװ6rPn!² doސuGԭ~2Ĕ:ANqW.Qo(/L2/WCuCzxH7<?"A?PY C|u7N'ITlEBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBnq ]J8x@+$T G}rN0{uGjsVc )'lQq db4Z9+lhVSUd}E`>P`L~O4Er7wB=D1t2G Ch'grV7j[+OߏJCƉ:y%͑ߗ*Pd|R y>Z s.7e#%Ő}-w˟nꦲ*pa2meܜ|KEǪWֆ0p瓕)iQ4z'ܮL:<׏l S3ex$L! $`ۜ3D\+'ikH*qP-@; OvPTˉRuqefS!% Ȧ񜄼g-S-h(G#n yʙhxZɤU6:B#0x*Q*ᧆ.Cbgs`3P׫=Jڳ0dn-c{Зw9p>X|+gi9UتL[IqynWFFv8PF;p* 9)\Rln#<,'h=VC);0>R;&pl)9R9K[s*wȡr\%9c R[QlRMe!$uH݊ͬb^zV2r+7x\E!'Hqi'a95͋6TT]WޱpdJX%(sHIؙ)ʲ6| ǕV8%,QuI x$*vn GLc UQ/? t}D}~9y^d(΄cx42E7 <'FnkmE7vHT[KqʲVb<\ ^2~ԝ{H㔻.#@ت(|Ў皴uQ* 1\BʷBe-IQ5+}Nh4d:12Nq}/nvi#mvYؕjrNUey*94AuWMe ZrM=Yxhw>*SD`{d~ =@p-yА1RK:eiur$Ob3cǽn_ :Y }~mg{}Im lxn4UYnkZ#NQmUp$:INvʱZC4>#q=;i=EW+>ճ䭞66et$uD[Y15sWkZ>olgp5 5i-0?V]Amp1-iÐr/P=yo䚫}UB!$at&gRN] yޮ02twG7+{ŧ}GV ]vN-+hPy6JڂVjtcd1kJhެ6vHZiT;Cp=vi-8F[7eHʔcHx**%#+n)-4od?zMLҟ8FhT!>=u5<1;QDzgi{.tܔ8deU˔ Y jyPJ.Ʃ7j%&q@m @“+%tl8z UҵTM. m,Yzi+H#ʖԆf ]g>=H$8J@%Ÿ{.h1DA` ]UDh{VZw23U.L7-8i$xW=V T;9R6zQ^^m9?9o[AVhw ^TH)q//(ng:^mqi43ɖ/$k3SrބQ#?_ؑA _\bcv3֋WtmO uw<-aRs)RRk/~}$5`?VwcZ}yiaFq>M!M[ǃ-*K[8<}yFnQ8hckȽb\lccMNʝne& GӵV*ef)Ds= ^ @JȯD$>T=9}V 읊 ɂT>䬎d[VCJP?cD2-Jfn} ٖ, Fް xHH}gT_T{jxu&d_q^%SO6$^)C WJetR 9ID!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~ 2uRr|5M)]V4DtcdOddpNg5좯U@Oa!3VV֗W|QUӐCsSګI[:#EO!C5Pu7>Lo4>%)QPUMԖk*Z^Ǐ.o2TpyZ!{kx` c^b&K6EJɦFK0mĺ$xSJZB{PBӗwM;R]SJ} rMtwfH\Z[y$B|u,e JFym.wu3ך^/KݡRT2SΩ*%|یNVc-sKN8=Ft$.i7Q˪W".vO[un^j~?-iϦTj᧊w~i-#­'MS]iV3{-LκjL)\Tw#' St[3NuHN>ظ/q۬Ԭd26=oU2m[ݔܦa-$v ՓaxÚH?luiHM)q) Xi)ly_^)lwN- p}aw daoCjQJ#5L9n86<Q- <#S@Jk{'(1ܒTRR;CvH+})Igj#`iUQ _yQɼhX(Mb W7dl`OHIvU٫l,zFA_֗~৲]4 l#E9hk_.w Z@R<391A< ۈ>u.nђ6S$([T?DJh#%y!ո pMx1u𚤶nO&DOu0p` ; ֲmGJqڽYL\[`)KJ >հ<>3E$USf)Si8sbnK2ɮ)NF>+ `@gT2e NvF)zFr3չKGP1 PNBJAk.yýSzBh9HKA{r<,q9'Y+eޔ*IN lKuV [mES`Mvq*"mI4jVԻs j=QgjL787W'V/5[@7SI}"[6%E앏44' I][,>u8p^_fSAT@ǵ\M,⊬fǶ t@$g>P-_V$ -mSR, e]a9 %-6ִzTqpa8cbPIMtövuwV2Oooe7f?V{Lǖg2tAqWjh}VOh.5GP@=ǥþjLFgqKh hӅ Z⸲*D+n>*P#%nF\nƏ&!Dqۇ7VwQ;˂-n2}!U檋; յ`uN p.6(jVpdӲ.n ڀ3zRꉻG{/v RE}2nG˴ra8-qW\[pkCS[Z/HLݻrTS؞Ie!ouNN rR>2&+.]-2~U'Oj{`=%Zj:nߚΣ:j3N %p~u}}:75}Qq!}\RPٜOGFY"{O _S;qb'T`ZڠLX9)>UtﶷדtsJڡQ;a:Ip<5ϗOG-qO-*Q=qIܬJ0#WU'P㴥6^?z4G9KE'ci1x l#0JNJ}O{FIKV!_C:%a醇~Q(䧐 =w٪QZc.#|47\=u0dN`3*eڂ%*D2IPU>ђ[P1rrr1PVR:sw]cna )K Y#nӴI-C:~7ÇH˧p7]%na2%\hm9QXznm7 gkr3o&Dl'ez&s/qv-zAcO5Az˩}mRFy&l+Ub IJԕ{DL4XW0JeKR oV*(ZA.eN#+Т:׬pz j9־#T]aic'Iٺ5n RְP\a6Mqm:8Fh}IAR:ۤH (# PpI7Rg(.h!CG&aiJv3Y?hYjK [H{R·пPJI<' S+.4_`HUɀaøL$΍ʼznm/unfsq3h. b7}\GK:MXcI~;r4F;7>SW gi)84UD4-p$`+*aYʘ2UCB>>ɹ*K + Vj&/y-W_C}S6J.a)YI.zGm\!/u`b+wm-R(BRSVԂS/pZs^lrF߸p 6ߦn8Psǵp5Schhr <̦Z le}A4W^<6sZ@(R{[$?/pa2yܸG灌s^*\'=?`{ra|SJ*CYqS*|I.qs:9ߺn4E ioJgpN L:ԼxES)9RSBp֎tUpS+I  *7ԛ;JڜJ&G$WHԔyc%X,FBLKX#84x^yˆ#<91KTXv$  \(ϓa4͉ qf^?SFF;t.Rt )Ck dKfх+R ⓑYe+Jof= KGі#2,y#ѧHTeInn,cU JS,[wM2&+$mQȐ)8R>sRB6erZ϶CgTv-W- u>u[mIv RN[JU1.BWLni1[7[FB~j!vitK(mBAPڌQ:Bˍ6a<j+PRr+Bqğh[ۚ 42;NBl*C+p GU62@୑w yS.D6CK'**[vS1~3ZvE :۠>' F}5)r>jx8{H9ӏL}?PCouݿ頶ڙ,sjcg^COu.𺃦e1[qIgW?MG՝&`;3s_[kKu/q0ShfW L3D{(w^8 hNͰߚHmϨ_ExitD4e9y>4JǚWzFs]]S*c7lnVqo ʝ1l~!+ۢvTVǃ-9ҴT=oKJt!I wo}ݱE<—Iq *WwsMOPWG,4~EɷKJ,g"oIQV֒~k8;mOmbhVPB98m,`c|c||HA#޾Tٮ-9]Ҕ7<ӸdG Iة^FKKrK12;7i`­_50d|!ҹԲI]._t?W[T_H폢{dA־iKߔ-1H;K>Nk᫻>237'췏Btr᣺;2~ik?QIto}\|3*K;HZ B*DlB vW jH` eƞ5U5+r[0q CUIJozM1Y g$dQ=BC[1Fuq[HUSrHXz@R;,2PJ=°)ke$p1[OWi w fpӂc/RkYW%4^MWn%kjNk͘MH)2iYH%48qJnRmEO̼[=oket~Acn:mw$)JՓ߽F0ԕmNڗ2#N9 FE윖~ؤZ匸)[_N`v 20zjQNS T5%l jL̜MD{yY߯nk <) )) 3^DRmQI:Sc*?$!IAъl~lѐF'Muw[;0k:co cINpX9\|Bwh!=kwPW☒@;s_1.qLT)IQ);nhivVM= /Z³5_:o);{{sTlm(ӍʴBAnkPKINQơl;!ĐX^J;V83꩜;V)ܕdsac=)sL[VRvVR-zm2WDGi ډc$`% [w7q=&z S8|Tf< g6Lڣ-a䤨=J]_\p L.O[zsӽ<*L|U vg)gjD4o|q}UK)SR#s\4ÀߍD)s+j`18ucÆZv[rEW9l>j 2Me]IYJFZKw+U>Y}Ge S;Sk!*WԎ.pRTR;4yD%)8 Z95aGҤAѽ@4̌EROԌP[V;%kǐR\u>BH>jNUS4K6Y1j XTA U:(>Kx nUOEÈ'T/(`:7?>dt3pjsAЅ<;Iߒ~+fw|g*}'Po\rr"iPP>I)@,nx0NYΥH8Q6PT iN-"%/UH D' T٨nPy8 zNLU<2[J^aEa:*]˂'8@4ϓnu-S&QWrkXTIugަx~}հY#=#vүE#tyjH8\\ٌ= RAu8/;M͋N[!J[xqqk%eQ.qq.0U}US9a}m+xLL2R8\[kbhhxl7Ou[H\ rz;|1˩!qLm$`}dt‘Q`$Ȧ<0N8sXzX V=s^$0S\SN)8K=t!9j@%sb6Q]TqI_; 06~#EՇRO(`4Zt<`Si(NHMY?O W5tΩ5oz7zU saz6RYMlNS+zTFQMpj(g-+hx%wVJyhMmܸG(Z8* ~E+TM)Op~Չ+'VM\i LUeADv2iSi-o$=>*& ed';QRrv|3 8jҽi* VNVOhV,LGBvQGWǥ*Ƕ OHPU->+Ӥ\Z'I-'o/ zjIa- oqU/vR\fZZ#3uP-ONø1ɨ+iH㾜Ziڷg;{V_/<8m>*-Ғ0G.9u| ~̀S4pQwG{N/{~0DKTA%L[(QEF*6Oj1*EsgJK vkaV3g(`U[H Z]'O ֖?LkIw,PsrSO#V3?C)<M%N\V``J쑂X\>F;0섌*+0œHgw}%,>O)X ʋlFɜ=/ӔҘ-F[sRsX9$MSGzNqRk:>G쐪HYyyJWU˔HF[Tes,$ tL&;) xj Ī 1VLaoAk)NXŪ=6.a.'b'KQtuLvtNO]Kr=rtP>e堄'c+5UU 2}OimT|ȮDF$eY0q zGJ{ Ӻ$ci۽%$HA>jZ.1As`c0OmNၪ{ĵq;t!IRʏڸ&:Ghh+vKXִa#GTdʸXQ#-K\z"Og{#-8P"I+18A>TxRB)>z2/[6P0*bB׀-)y$xhb9Ȃ-ԶT<櫵YvICyiʏ>d@JlFTZ 6pcsM*fTb41$Srkl=McAeuӞSBW(pr?j/Lچ֕dVZH8'K$˭8+Ek8@-dϨ4ђN ojxO]`ʌ Bs*]E%FO+:bژL.+## .tKKͲ!`>a-;c_dd3_8~ M);_7"""""""""""""""""""""""""""""""/{Nm#k%}q›9@%lo*.yl3{,lm2fK?qT3-vm8L1 Bai Im.%%[NxFV7]C^dgI0 MR\i%\ڙܚtg7W}IXlKt 3y)>Ӧtz@nH9jMNln=l*ܩV0Q r\el>(P;Ox?ju e)ᓸG(jHoD)yOdsk!.mA.Cm*t۪iYQݞ 8y!d`rRFDP3޵]i])+@ecNn"RBrXv6 *&cdvH>_*+tz彖ۚ8jKLcy h'!Ϲ!X?ނJaD.h٦NW6_灍_uMiiYWin {|縺dۨl0MP{.r6ڤOisyUg}EEA47FJxM} a#}M $S_xOR<;cPn;!20C6NVRYm!dfR+NLAd2U gPP5ӪV/lS.R"ox4$qJOUP~>ZIG?a3 MG !=%8 sqw[4J UÍB@m'B߮7+ oh wCWnͬ.0͂{3 Ũe#2j{Z(n]oc8NrY䥏wʻ'ρ+?ωKS}$* R8zi,q3;.:(ViT"&)#<zwzS FU)mF i'qjە- CΥpfXte t4%8VOqHNNRI8g}0҃jǕ{bC^j˰Ry+p2lLdz`Ou#K/3SG%<Rok('Bv'/g1zm-khFP>0%+S#GӿY큸)eKj#Yym|+8+%YP'^y³9ST-6TԵ.SAֶs1^T^s{{L :94F{+ҷ2'fkVTА$Imd孙Kp)d!Qx0<ך@ \;|2v` 2Tl OsQ5Uy٩zrxdR{Ŕ۹cMH\2奻 ڌڳu6)GSHXR}66n5Za,'j}%aDBK4e$>=-6]CBUۄ Դt,3;!F(✵͏zFXl'*zM2ޏ!։JTh,;oM!,5%M$zjP#Ooںo\1jfk%Ũ I85tN1p2~L$x6J`fye**}kZ-u5-;oŹJy'5@Lg4ϦH-ps%b:X@ʝ*8|]'n[ϑC.'>Sn {5VOlrMZս6XhIk*Gyc.kg4?Aè1n i@i9ԟ@K1 MD`SNs*3,8sNcq}+Vt KBO~C?ZtuaJb݁qO]Ԗv?M:GYJ|WBdtv#VԤ1'iDؐLp&,pjJ WDGA8ǟ:Hyi^!RMGonXǺpMo곧!n}bVۜh()LkOѕkCg%GPR*%l%VcwͲs*"߼ Ψ?ڶޱ&-P'9?(?)î=ܮkgL m]3`6`aӟw[Lʍjn-<(;_ -԰#nN\< Wk4Zh|(dtZsI$@:P4a< uOS0Z5n]=0z$:R9*Pg%:yy3㯋P=.9HZz+#=VSߨ&=ז=gQ8uIKG``5@8LN\J@H0:\5Y1ACǽ?N7p\8l*{N.FPI)˨qBiLմr:b,ixDbj{2L)+V{PlSZ&2םc8!@q5dQ g9DFR[9ZͲЮ)RlNgOjMahf$*-^ ܥR#^M=k*cp~]eYw`t%!-+ev+ޣ:rT)UF.0-"v,tPQib>(rtQˍ1S0d`iHIyMAq)YɎ>T՚R.{T’ U}Aih;5=抶<͹YSD 'V{}¦(&h> UZ*# 鞢e 8 rM鴤Ӈj.^{3ׅzlHRFjOm\g9Z?k{ 籮@뮒lʺHخtzlܕ)uE;[oE _=ԍ,Cn v _޶uh캖U}j`xtWQ}kNFG_QԵjPT5uv!-={.EȴJ(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B0qɯ\ur/6M.#^Ӱ+])J:9;JZp~Cuq ڢ`sTʷj$k]jn(`9Sӹj}JHiҏmCҨ"2PI/-!jH$}WRӔuv hɭ_lX+Ѩ3 Nz Tm8f;lB_P+Pʈ$N3S>g@DY 8?Dݯc8o|͹ny=tĎ *zW^ ׶; X^ܬ58Z7:+s54dỂs ))PP'Q%E Q?U1#sw/%I?3b8NަLo9-lԬp)RI^4BDKJ'g6PGhIYcenB) Z&\- t!!aNCs)Q5nێ'jFO6$ Ԏ+,BKnNFK#t'o wR|~khRrmu''HY :u3m;j veFTppQm緵'97RZxMS^ vo㌑[=DrvT/皥Jw#+ƠI I9ZBgCߎmhyw Ưܴ%[n1,oOW? 5T&MW͇5Dw$=;kJQe\g]jVb-vHO2 0Mm#IG5JM5w;c RNz?!۸3C\ X٤&3aVܔ-%`\ Xa^l9\{-64],Su=ԥh%~KSMQoznX`aIG$$f}_u͔S?IS~>tWޛ3#FG/CJpA_m쌅XZB^BBBBBBBBBBBBBBBBBBBBBBBBBBBBBJ7vJT$8Uz $eO툓mLnmSpmJh n+yϹ5zYyk4H#=ttQWyp8d.FDr3(!]YM #ԯQՍ^{Ѱ!tB;BrRa\%|-`F7* KP!yR83 ``T]D9NZ7S[]`\}ON̵CJ?J )k;!*뗓F\֒ w>t~jj?uaԆ !mcz믵w"72 ihqr܍CgnGS8Lil jJT'9q8+8Σ3-WwtT-i?㦗&.vn6[hZqHF)XtmSgFcAF=´t:߸P{Z='Z}Q*g*UA!`zm?;n7L\vBTjlK)jhF* ۅGSyC{gX^tީj[4e.38ڂǑ?鎢\![^cpGQ؎)m#*<GtZ!wiĆf:63'$R>/x|;ä hhִd$ʬ@PI:'$:\y+?jTY*z)疲9рYRRTwx엓 X]بI3- [K.5.]ٻ;Nہ* YN}ϫPΟ CTu?N|gH7Pw/%9{VvVDīpP*lR%N^gtYH)h$"6ܥXp{v~n&SkWIvv)j&JZn&*E"20Ut 2R~cU@[ukˊIJ0F|fRq纪4BMmԽƀs±sZqwR {zCݘV؃,3LYI{URsK{WB_nwAf3bS e!)Zj6-\X8mL Jij;p5(י}do0FSڤ| |SMm:q;1dmt¨uHKWjp9B:ֈCC'9VJ[JO3;v)ˠe;rKj'fq孩id08Rx!Vzzt5hVa Ll6AZSy9m>ꚐJn2< kBJzkTwn } NRp~|x)0mTR3ڲtCp|g .pF 8ۂttU>xrANzTV=,aAM |; *4bά]e6 nVB\_hk +4ﭵ8dd߰5 o$t>S;Nky %n:pV]M!LSYD%N/Qvi.S;Y8 p'Q߽/ǓS[eyQ$>yKO7GG >Z{-f2)44>a}{:ZY R٘? ;^jkiJQkY/8 =y $o:e6ۏ\7T gQTᙉǸ?B^[Ns,JWV#%!AhZF7A;P%a.WNF3t=gLGxn_iިɨٍShSMܝm8wd0f6h$Ə-Y%{WBLff;k*J<ﲡ_f=ZÐHm, z{I4PѼ̗ats^qr*{[m)yBH_4:C]wuT' lT͈r//Q@}d0nuY`vG4u9k 9WKK2O0r㒝J=2[jחahʸz}{ruALYVU.eC _Xz-Xt:?opV?/v JFCFF+s_Zفޣʱ -n7j[e*^Fy[A m5=g&>ke9O+R"Z;g+NΏ_Y ik; 2B D\MU w-|fbgڴti^qoھTF_e<)ݲ2/-:$nT6I`5,SLlLL9ڔ'>}Ag/n0'S' $RncmK|RP q$pqڙQ+Zc2=57|4/SQ78)hg .M]΍JN\bi[$` ~k[C/Pڏ%r*fE-;6A$'Jghaln+c$bub%/7ĭ}Iу:I @dgչVMX(~ƖJhǖO,:dI$QmuO+mF.KҰ?8\'e?[{ ?IbCS `{ɋ$!a?Q#lPRkwI!4D8- sV1޳龇ޮ ک-CC38Y%<ᱷxjjrnz5ɇTˌaM'R.tCKH# *Z+$g-p)qSDp3j9I#ޚQub?Htϻc%N%Sʤ7O9̏4E $&s#cG ;@>dۃd VŖ6HIHsr9t6JgK}?hFr}{mgKA $npNtlzj3C5i)f2JVTF{Ĭ\N͸! '= 8^ZL=U`#2\g uV}A|Ak*ɥE+9p;u|:WbW4bF˱~,)%Qh)qcmqoC)NwAn+~iC6TOi\j gn~ xC/3uc<{.~NIY H$-FjH$dwNh't깗 iV  pŊm82sX+ܴ~$ࢳfмJq×09$]&p99SmܯKĚCṫ{`ӶB^76 zᐕ11MR @HlQJHNH>5EոB`5`9Bs>cQ&FzF| 977SBY7na|C$2HJ@PS1f{8˪)}{5-0y@8@wU0o))rq>@J1A\ST8Bʊ y$◵STVT6v=$汎 h?É&Zu([JRN?c[nu-p-sO;U[,5Tx;7Q_1V[\IOAJW(nQIdR=UfC.dPn8ۥ8ȭw}3Gv lO] Vw|KkwlqZu-O0.[nf…R~৏/ vj"Ӱ#a[ӸW2r3VZR/_4E"_9V8t#V,nTS8wQ4GzOZ b0Cw#ՊVeN=Kln̰ۖClY?\[/[-@ =We~2Yg hI}uXkjG86XherweNeAB/:2Vܨ`2 -o5ZIa@IIIo㝔-CI@JyrVd $$.)ҝ#"yc-^C[V=/]F%["I4xu\$cޜ?)K}'t;>|nKF@jWBɴ<Պ7)svhWhR #E qϹKO&[RzףОS"2JTȮI_I4mG+ftψ7 .\;}s|i9 ly{~}%]ԐTpW&\KaKC ðBt1Ja] !DN"f=*9>}=499{y ezrIl$^Q*b[ʂ3KP [d.ePURt_F׌)0{duB0;aV7鈝prBOMeD)JF Vi<{{$j+)<Â]`)E=X읡7*9Q}7tk\e Mp'iC9ziR7 C ǀ5U\¬L[{kL V;å)#ޥ,74SS<^RR}X{N\AQلlW^ G5_w'išf{9%/]ʔNi˞u9ēr67 hF/IVR3)Lz&)0s!Y )$T#-)[')eNHJprjNw d:rAtb4iΤ!8x>Waxyӽ1p:zؿ8q'G 92@ONi4k"~ov@>?B[\@in~M^/#s+ԉ-RGڎjas=X^ii)_ rV Ta2"J](w[:>/MNޢ)*P[Kk9v+>z_m>eEY?޿Ig.9g}F{wS:0~[.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~䰀j'bʱg&-rmEXyQ#e 7x& Ԗߊ|evI*@j==<.5єwM4?@u[m/O}?tWF6 QnoVgsxk 3%6al;X-se߮&U\ /ڽFݓ(Nџ|VEM]E5'60nApqo :zG:YuHvq֭[UᨪR^py>Ê 1h?'}E/$;K[K^rLgntl8)+6:MY\e)o 5#ұњ؅WVt́q?551n=ܛedELʁ<`8j䷁!XPkj'}<~%Lbt&zrz&ZA|$rR凥r{kK ZHuhQkkqCaݞP\Y<~-pR̈N`n]tI@kJ96ީ-yn: EyJT4c]j;efD;}\YRrkAyݗ8rN[nE8{ʯLEJ0\x]R/M\n]irsr|6?S xˣ)vX$8GlGJm竺YچkFIG.pr湑yk*ps_>4p05ē)xqvvjckpp"NO)2qA4uu㮩jRԬ^ѝ!ZHQBg`Rµ&Tڇ2B?ͩO (%Arꢩ9u;ud.={*Uݑ6;ˆ$>\>)cxZVT 8i J6/a (H^miV’U(y,\X[ |x$^3 ;rsv[Nq)-;E^^KSI9Ʀi,'>C{,\VҤMYR}</N$Z)Lro2т#FR4$W)= (~5@%yh-ccK*L)<5GlxWVJ9rj"L(Te2OJX_L3o*z?SۮhJR[!8?MGxǦĀC-BquKKaM!i>efJc>\ n6V#sY[[J1[KόXT;VSLyDAWۚc]&:A*F  S) JGxJ,ZիRTu"E씣NZQ@bj}ODK LȂB~6W\m[49.4k__:Qquʜ 㸭\9]E }7-hpL6wRQm u=ԭ]<}*iYj)BʏϽXaVK{IʭBj -l>q UC5~Ik_E= 5չ8rۀ:VJ /Ba\Ǩ_qkv3x=rQQ?, xY5ʥRw+Xtc*G{sF )򖿘?ak$S^ 姮4*CvvF*ֿgLiJV{2Vkʏ (G;T?RM=QwM"~9p$(T+tԴ:kH_;ӖFQgjde:2d'q228I9ͅ`y5pi#7N1XC)'hI2r U?dBAJm'jBs܃b 蘾6TCXM+0j9Y4Q mAcްi4SšgFBT K}+$dpOom+HV>}OwfpHpx_fW ڢhKd o(j\12Cק:3t_em߅wb~ tI:M:03'p?<%W]l|U.)۠1}}T!H+ Zܖgl&Ybߞy:q5TI!BQ?RW*5/ zBlS7S%oήZGl} 殶kkaÚ{~ǯcډYQiiYTW֐Y#պBS}m?xe_1aݾԗRL݈?B4溍LmskJX:zY ]D~AҬ Ag-p_|#2vn;%(ڂW>罎+G򋀎p>էn@X ? 'P5n_^۽D[nVL7ϧ@7:uoϲTs/=?Fd.q_`ɢ/BBBBBBBBBBBBBBBBBBBBBBBBBBBB$<Íܕ=ϵ|b}*<b 8j~:=In윒ߵ6[R[KVpɀR|<! MFl4-\t7Z SY jUH;F0/ UT r8~j]IWL\C|ωN4k͛NǙ n8EN^+󴶡a78Wk=d #{@i^q(*'sI{`+w[tVjxyn?M^}c{@O\̺6ɭop]kVTMpy+y;\B #81˘ݸS*J`Edqr%J9*VrI?XP}\}Ձ1i+c_鋲lSѹI$p9jߺf&ϒC}cvFq{|wU'M{wT^w#|[DHRpv? L`cmUs 2 ]9 )v\j49׵@'*ρX!1ΛKD8NH/Vcy g-Ԝ7MuMI"q~j^l7|g>HgTov;oN-7iF4Y3L{-+s+QHZHV,tLgJZ[F6p|Rum:w{o0nFɽ*# nwnUw&7,.+{A}J2F@'P=M~n:;bՒᨮ1mVخ˞m$q{]+[yofd S+lT:yNFW`/oXt@icv9}%SK O 8|L>^]+~߃'HxGzII-'#P&^f+Z.nr9ec8nNq|;ۓ8!1ⳗr ln8kչ?wR捱HuKc=qJPnnF ??<ӥL(;wM![N{^8K C_$어ڗp|.x'5[ O)ȭsd\tѺ!`!+Y)0ƌą0+ylCNA)q&7='Oqh˸Wr6Ni3WI 8! $2` ]yn]gc$tN+Gw8;6Sp$9' Y$k̻TG<\S.nIR(qpkG\䤫}3:7g fmL-gqk.n3,MFl69@'9.5ֵֆ? !oNqTtŨ HxYb^z+dW{!\gdtIԒ~,'8N܄HJIc2UQ3IlkbչI9.6F,*F6)Xo R{N4a(r{}HH [~Jg+6Ț(A[;31]E7BӝSA2uY]~d<9<Sw#&* -1t$`ޡ'h''`NANִň҂g)5GG9l 2Hcu?F.qZz&  [TIV۵%TkA1G4nvv|C[=E6{znܵ>~#[\iJ'[{t: wh9{-]Q,kx`Տp:~$$]\[HNEaT[ q+۴D$!A4.W+|dcBRXO$W2TSQ4A8 ܻe,OHAR-d I'8}+45&H퓎èu6Mx;J8usZ[JZB[jNZlwW(03&RuR{qlmʅkKHPn `VW!s2>U7l5tZ;V Fuc N;,Br<U}q@M6pEi(>9U;#2w-zojTk̄5p@ajd%Z"n9|+cj O3ގl2=U\.DWօHjK$M|Ρ$V~n@`TTׯ&zWpJٰ2P.tIN$7IJj vEVۤzH=U'<ŕ9&&{w}>Ԙˌ5 $PRI~29qQsxJWNl=xJ8BIoq' \*MLX-6嬨^@K>WA;Mw {@[/#ۅ \66d<stg@zpnl"; \!^>}V]R䦋 +W' X)*Gm4򝲹w$IiA^Umq/[$`R330Gu'[<RxEN6M*cY=3jVW ?ߑ[ {>PAӝYB2cf*ν[1BZ9BTSڱ+`uUlvrl\`W%6gyv[#%W)42S[CaӐ3R2 +TҢqrcrT~uM %0I8#Xzr’r_E풥7;8M `. _)]6T}3c[UL(?)Jx~tdSU4RW4MRCP*H=ǵiB'qKm:4W^Ysmf}.AvBxtuni/hrXd:~sZ5J.:RecjN_ZHb'F4JӚ2fO5qmJGިK[E{p]k=+i+ez=H{/B[>͕hfۃꮿ׳Elۥ%MHAؤ M]!-x8#H>t{⢌s]g FG쪭CWڸ/N:FzO¾Y We,Zjxpv:yg tNԎx8 ަ|7jWѸ?Uԝ0]A%Gu~56Sie'W軣Kd5ќh?u'Į}Qopٮ8kVeEEEEEEEEEEEEEEEEEEEEEEEEEEEEE_;곂|m._h[ eΌj^joL,E4dR׎5?Uk Ѧ&evZvt8>Y,jL HBzmb y֛&V qW7uW79iq\K,RWWStLt^]-[6v69ʱۿoju=;uf H}Ҷ}9e6r"4`+jK<ägb-4 ?_:*'uxG9Vs7K{J Y#3^.ˡ0nyEn ꎱc|O?Il 4_mC>I-C!Z9+S?L=Jqm ӓף5:Rr޶g.+]5:t$1seR͏Tenûi][5vK !3nn{!$=SԖǂ(^ v5M#|nI# .53047_*7'c[.%De?޸q:7]F+g3Խb.1 -Yw:?r{Vz PXe7oBuUSYDG5p_>Zر͕#p74'rl7Ufn#w$7;ʙ N]ϱumQC`QuT"8هg8*=Imoњ~mIiXjȎ ,v8fYﵖ4g-pu3= UΧeثߩk_vU]l/N$(׾?:Wr9o uaih!GVZHWrU*!2b8JOjnJ O4KDU:|pR L]qV8 ROɨj}]FH2IT `R.u Ͷ<-KN ~O=p|V[ky$C7g &}Uh%G%7̃pG?*9g_]N[%K\A# }OuLC9}YUlCAL8Y0j%p]?0pJ?jejs%)Oޛaz^5XJsMgez[zdesF\H!d2p3^R2+E} e(IP$x"~dnjS 8RMf:BI#̀0Q>v8Mrq!DS虓qNGG$nU, 6C+lu:%II)M`ہ}jChoIQ|_i-(9հ6Ji9]a𫋛G.6 FG+aS@4vT_ب:!.}dӕj8}5eF=Q9s[p w Cd7!1CŵD<~~} 6:' 69Kՙ )81U\yW!gh[ H$`v]@eEUDglgCYJ'pvi[̧`pKLIҋkK;_}^FF?sm$ӾOÝ{-orYIJq?WVSyLo-A%mO՟h bS DqQ|gN1ۏ[Fݮ鹞0|qEu4֪0;7۟m62l!m첥#qlg| yNB$^nB^CN=wе.߲LUC15G`k޿U} {_ `O<ukt{I =_+8C[vBHpS . l %Uac+uEKyM '?>N sSn! yڹ+ =[rC .A Z2RH5ɕ֪Jf]oH l\@?Pµ:\%U`Wb5f\addY:rfy OPrG[݁9q[y/ =nm4@wO)FF [Ia}旡GTo3M$!UR}oh#o[s1K [@RG*=HsN D3CKVȤ Efh2SiJV)AI:c+cCL{ͬ-3=!e?QO)Ny%7)r AvpΐWCaJH$)dteJK5Hek*ʬ*dld5upb]א¾v}ijma#0κY> '.oȀ ip_8e}1?S7BX%/S$$Dk ù pR5 E=[n[Nx4nG U(=2G쒶PG]|H+J rpnzqm1FK*qPS#zoNj #!I-BV^-W4pZAwk0v*0:b]&:ʏvv5&7qus4b9ی).$m*V۠eb7ϺVPGT g=^U-4]ZGӎw{ bTiQzfyyޙed7! #!o"āNpSWўڡGҚ#dAQm'ulyo+t;{zs ./zCISx m&:V݊u#_M-;*Q(!Ksey8!V^iCi@Ɠ2ZZWeCCeI[j <`ֲBfk'g~LX;on} $p3XYx?}uk=0"\v]4c˅qJ(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(Bǵ Q%$j>-Y_l<IJ+վt&y-8tq{swU ,<R T&hiʓ zRJu%ģw'ޒ- +:C.K+*\F(! A>lJ`_Ş}tqcu˩Dc&;@GM5 lv7*>ubf[:é9 INMN-3޺NK[-[i 8)VG lA21{*we`xXLrsDVvp*frZت2h'oޖ_5 wǹ\ymC)ZU5I@[2CaiϽù[ٻD7kR{Sm2X>Oe[0~N6UƫLviЅr |S R1SQylJzCsfUA\DYwCd,+N i;@?NxxWGlˎ96,Z#n=-j.Nݗ5IG&u~RשU;ϵJQ05Ljk75/#6lMQ:aH.fԨURZ]$DS4HBe=Zs4e4= o%ϤcNplfdƒ/:ۊBj I P8>kA@2ADZɕocmzrvGIB{s^GNOnfqeDF2’c1NͰ/y,vNHa.gc{R4G%xbZaM jnĄhm=)uM t}?s޽'NB1b)X5Fܶ#Dk?x<5u.Z2K۞ $w7O30N2n${U +gd3DK}Cmo>豔ﵵ {mö'dZ-w^9R3Du(#k̸n;bH&)Oqo0͚6O! MBT`Ӄ6kr1qR1T ‘aOճ!͛Ćb1PVW 5r>ʊ:3ֳƆ!p7GthDnUQnS-6flNn\[40wA4CN=4/j]'Q#6յۚ fS\کZrf2r̸/)izxo֪1)2@K^t[>zpn.Y (pa9|jއ'e)gM=8vf˝r q9e!Fu(Z/WoxTWuIV@'*H'^+kNOWKolX=s[FN Ri18j@ UVeK]˅kByZv;gޛ)Lon=5[Կv:C?ZċZdߩ R?hW:d-MIYmo6rǿpj}$ݔ8֗ j *GԵnr[gNTGud9 kBH榬~#UA8{P>d>X}.^-RQ8znFҍ0cs\Ҝ5w3z*m$3_JzIMt.qs+3GSH^X 'y{0q־2x^avfjS{ovBi-p8 P7:ezey>.<g?bN+zd{.hñ:G+=11q5]{*F\V^Gf=΁Ӝgu?]TT@i}֑w^tqvnvWkEmʓK_|κtmwOmmn]Uhu3r2q>ծaxw mA;^6M^xwfP M`&r!8RN`irvN~r؞JRm%05.O.B҄q*:hpS ֲ[nK髵єS uU#fkE rZ@*%êmoN8Ti[ޞһ[[=PZe.P:'{8aYzwDVҥcD> ᲰzHqyJLtyxV &δYXxǵwJN&Z֖`re ?;s~z ,pT5˾(x%IᶡN2'Lll{*NuxsZyww*)tp2+v4/|y ]Chlč.J0wX'{i k>yKʶLmOCgj9jwzBe6Ekov:~f?uQV}quԥsڢip#'@ķRGcH*Qo-CDٖ)ϔeB  [G+@'{nRsNuymi_u]I9ێ;ڤyJl2~;Y,h1?^Ҳ_PPJRO*W{MO}j䕘N*6y5gqʈ3ܥ£ό֟w b HL 6WlU0f)TyݭnQ2c%3e6DK7*u0nx-PHDOl80쇖#$8vdHFђR=N\VޛϵˎKnB}$.Gp+jxY-oWy/xi7ZAsq4'V6@ltW8i&JTyZCRHdƦٶx/aN ӑ?jFba-ipH8|qE3>놉CcqmFԸ2;V2OzM5Ltlď{2À@)Jk/c 4bF{|LrSȑ\g"iE mc IXJfibec^2=I1fᓑE!KWg$ >)0qk1#Z0wY#;|SH&WqIFR|Z~kR CӜ)X_A'oiY?RIC-H`J+1 tLyxX6Om x7t̗H*޼]v>YG& Q#% }Bl;O|BB0c-i/2⒠|Tq- _G0Ӏ=SxI.W;fA->sa*!*!;nkǨELW4K\A[çkVLrTSzuU Vȃۺ@zRtAh#9vqC}s>.3F,OF^;~D>WqT%ѷkȀ!n2(V ?ުzE#uHM# OU[.~?Iu5al$Þ晴%* !7[^3 \3%BY(`T9٪YOOTg2>+1յܷ;ԊV Yhw +'dz'ՐcZCg'Р2׻oR~(k$3Vj,o`AIf#r\u`g`0[YA-\)١Vm4'9ʻC΅heVK4k+e#;IpSj;tLd#%^5G]}H-$n ^R~Eڲ>N?萫U_}/]޹ag*IIʳ].vB箯1/T[C(+kNxIH #mm$Y#eء]=J7ǽZlj{Z(%/v'q$nVi t\a5;0M_jԮnT3KOp +uhT/S|2T寣]8RJ@V<֝An2L0HV4(ӄ%}kЇeь)Z"!V jRTgع:^0U濄6ŭ; k!'r&=H㓅ȥ|R }K7 Hcwn5yҦRA'$A;,ua2RE=slf: +$o% TG4о[($2I=M{@ISK~G^\E;9K-,vA;z}L٬lB۾['}ΟF$}=\-2ېBCH9 {OS&d87oN[;kI/`A>\0E:K+猯Һ? m+HM'SpW2-dc#y">18#!De*Jr=ޜ+B1M[N1N@<Ąxޱt #6N0PVw{^fx^r*eD@~w{%1QH2=!#HA|12S=3o55&-ZATlWNr۝$2)OVMIy?n 47yNK@TʾEhH⽪6I8Ó%Q\0 (lS s' 'Z47Q_D> :Ϊwv46K\Hn77#p]s]h[Hq>:qпs:S2K2(5= %VOK_Ai:ᐵ9 u:S=3ۓTA Q}J1p+UQIˉVgA M9iSjJT;ӧCߎ ROME(#!MFpWou%ŠSړ%9# <_TL FɥӍX=BtFZb3 m+ʏsSVdrGC|rwzP_{r:b1}Gq<ڳvtz~{dç:(X`.]%O*%McLպ ~ZyR;X^X)IGFku7.V| [n^&ISTwZr0Լw' ~|UTMbn"Z*J=>j )~nKOVVG6ߺkU`Y".vZu^Ux'5kaOgd͊jHLnsGn'LIoK){%~;o(m7)RqJ= $k^흎M*CӌeC0}KۂbQI>Lڐv-5if_]؇ ˷|AG`*UIq{)K5&[!.)= 4̕n {uZn7 IeI={B^_UNp6י"$oN;)$pTL8V_N5Q )1r=7M*&h#/  H\H|%Cܔ̰\J@P9jNGLd~v*ueiո粎Bkb;dzay?S¤\b?Uz!ԙ/-0DoW:L_sx۲6 {/Pmys0xKk_ f3]_g ۥ!afcgj@2&g}8㬡i#*~V|i=pG~%i\SV<qsp)鞉y)i.4JlO\V]+oJBsވ v +UqWxxyl|ZTTF1U.uk>n= 害9oR U\y\Go_ ـ+ ?e+Lۧ}-NA8uZ[j}iuBWuu!!!!!!!!!!!!!!!!!!!!!!!!!!!!AOkއڒ~ϗ B|6|Wo Ats/@J;/VE,:hnWd)jれ u׈]-uhl"H qFٺ^ H;Kj[\뤷ZIQ֚GL flð`r*O=ǵ?\Gus]KƚRng3.`J8d)5qoi&,\(+pTN-K*~@ASi;Rϩk xϩ k1}镒 Co)i(nrG`Ne–%Ӗ47S}P$5x{*5n%.`y5^k7NZ^an”yP+6$/7 ]2e!~?w[xQW'1.\яSpqb1COlq }uӮ&S/H )() v1;u-58(z_Q-e"JP +lY)ek`fK$@8f3 j#.m2m蹧 .rXQ=}]ශxjdg+A'sc]),e6h#jOP\{J;1 }TׄSG;H݋%ջ-)Rgڴ%#fWJI捵G6K7 '\lԠ$gOu8Zdtqqaf PqӞ獕vzHuU338琒&bnĴK/FjP֒4=IG:RlԴRwWNI%<;pgp'PunnxS[B'ޥF`'Oy>%Eja -ˏ>rO`+k89c ?:\ OFrc+(W7e'>\mC;߂ZqAFA)u>{.uE9:f|'shKTxXIP3w]A~nȱ&JYu@} P [ϴs(JBtHݮ'pG#j<)uKQWe|;Fq[㲖iha5568%t3} ҈Ժ_=^ۖ/ Lv:w}K;P!#q~ x=i$݃ 5̐>;7PkNn0R@3g1{!}KQQ$'\=TqsrIܓى8nP$B)i29ǮMVmMLw:'S]{lC=A! rźN#,"hvAd JLUe$}† %i#7A,F庿DȄaeLN{֣h99 RCKr-ݜZy͡JRxlޚꚶKRǸ9${hZ64\5܈ ׀B?u K\nA·gHʇD~Jxu8KV0Ȁ)''KZ.F 6|Moe v\&tċlJhZLS԰`敄n}Irv5i\ǔvvԉ 8{O<^V[DRlSnJ}ҿN=3Gg%ՄM"ca>| .4g<=6zhA=aXbPQ⼎RNl+LNJ_nsW MGiYs߶l@R Ax :k%ö*=, pdq vzGHdmnS789>W+sKR/,^p0'v?2pc-Qe)#!EgXdܥ"͎׬i@2j- {^v;`R8[_*p'4ey%> m<\TVGaY$%Qzŭ tuč'uS2O Wvz~燜 ]\:]2W4uUFuQˀ؏Ss\_}SUܩ6l3mIOl)G:2T?UQP*>RjD;:F_ODB!d}Ϧ@v$˓'jգ:)$n>Ҽ}\VLqǜt7J$GkH;qKk}7t֧V6d #r\'dw#qY434-頻}w]kAyZqP<3%;G>n]s d ոa^ݫާKG!x-i mP0M9峟")'5{IRBIQ8=›01쐒8B6BEƘpWi]W(`pk}Enb6ug^L̚i%)R~!;zA Ut_k7 _8QCug5_$}{cy>};l8BG>`zfK8zޠ =r$+))7|g< Jweq3uMT[. zWߍ3~5_~#w::V7sᫀM|#8rԃe'ڢa[Rj 3Xiq6u#7p@u1IrZ߫RNo'J 5t=CA' i S3*@'!ǷڰP72Ѥd\H4RP9?5qs[{,F9+J_QzwpGްkrpdYH|R?zFoܤ,cq΋ +_ x1}K=k}kmCqC+m@ v#s,ri$oq)cZT\ nY8a0MO{}T=n^3'iY&|Ǻwa!lY [C`X#Juk/ {]n8F525r,qU38>[_$OEڹ(jCsA (2s5ν'GEUw=kvQA ۾=Rh6kxi c98l?|ZJuPC%k ;BߨpN1Yպ+c?Ð8ln#Hbt;c|o߶W0^Ȑ$rN*zK@%XiVĭju#i²cO:l8:PF(͹*S}"d0s#OT[)ۡoԸq\}mUճ];25(pզ]1MGIJGcڹ_RͯfZDy(eS " 'by l逾]%;OfvAq<VV=P|.aD8צPObjVAPH?QySsiښʏB԰)Ȝ6\lVC╎\ ¥úe~:QS?RGI+&mnzHwJByNmNVA*#Ma0IIc$4,Z_ܦ ݜ(>qB=Q5)+JƐ$zpy ao!=T[AVS'75Y8)3 $wN䟖h~ ڛ[8rWԘ2U|鳖@nme);h{$Tx@:VN~qªۺK?akAE P XVv8J܅Ȥueh;:Iy3Rth9dڑ]JZ$n ^DpDe{N=>K8)Ǚ3E2y<%̙ cMrv漅K)\nJxO$~}N%vG0x&T4slkXpl8GڻnS+Xװ4 Zc(^ q{}cM3z#FvsF{ x9Oo`=ezQQDS۶}STnŲaZ$ǔ7V-SkLݻ+&bg NVT"OٜvYzr8^pU8ǥzZNMTƋѥ:-OGIw)$sޯ~׶ ƵQuݴ'm}tQ$'5âc\6CVO1^burW kz2LUˆʤzq{Mhح9=:zC>PI̖֬ o]wb}<K9^PEEEEEEEEEEEEEEEEEEEEEEEEd"B+"/ܨn*O+vR,ǵ--XY-ځ8HR0? >iV˔mձejbʇsSAJe%,|Yz[-%G4yUmղ ` hzˎ\ۘR<>@UJ{}X_LZ4X Ϲn%mNq1i±"upZBgIL80BR08L0 ݚ>@suGjˎy==-c6a8(Ajm=&i~J} ێ듫nlC ?*R)iuJ;+珵lGF uǰ*CD-1(ӹİG!舂[; jU]Y ։S`mi%͹%\_t1ˤnnqFF;6v؏ceu'MkXsP]Y[+pl)8!ew'޶%Um[Ԃ a^r>^eJ;YzVkL/qT矧=UGC f EP'#pAoj$= f0x*%8rрy>29YH5 SOu4dak*;݀L2BU&ܼK=o\&K 2Q\p$%}\tl{c287Sfw'ui'LAv~U٦_3_k}W d,y,+PUhR;`V kZ8]k\Ө4r挃nʧ\Mq';Ƕ[[]truq\hii3e)uv'**:B -epc :'Ỷ،u/쪤!s^H >F۪LR95b3ro>8ݹYUӷNFP91m짮}KOEYInp: 8[Uc2ڗIH$ocBTB|lxƌ--RPK5yK5RK:pMSIu"X[/|' _;H330F+|IӢ-7Ϥ26MQh?>"Kp[.t7~OdbeHhuZr%;I^ͮm8IGjt7;m{mG?. u9K!X.{Q&[@/o}eQ]g4$▖YmI!)'8l|Ϙ40859863-ĸO)'%)'Y'<׎$ԥ 47!>E L\xX+h]׍%XT-1uDc-[KhmT8F@'-vTUYdp()qJmC1)R%+O?vʟtw|7NS+^B?\y3dtZv4 Ӈߜ(dq o~3(ؓm7D8ߪ'{D['vd27E/ DrI4HX9VM6|c _-BT IR}46~'rOTANZ"rwTe-)':7ێ$7hn4T?] ogsTGFL0x[H*TK#n׽ MC@2[ BVo<ղg%V)KFrH}Jzz[M$.˴OOQ>i={U.1/@,iQwSjl#-.Pd4m%$+x(`qY ]EIp` 65 |, 9ʅυIHO}I*HRX7UF9ʭ56KG@H]6^V< }Kp`)E*穝>jA>'Û`8ESX6Wv;SVkeYPӼ5۩4X,UR9cFQBiGMi3;R5=ۜl*#AʗNVukH;Yt-rKa@ ڦ9迳Gt}^z=ñZY^f;PޭCadv6(SZp869Z(&wWخ Sv:wp=xI4DQ6'|3 79WĀv+,\FNS2m%:*22sS5{9W9,OQNA{ #LgH/CYVx@p L)*H9^ 9\rSN\g8RC)zmyIbLy}[)ii gp3O",8|9&EG$Õ_Q4! em2QPZ.Vu8R7}=j(eèdjan~F@*/;iBf.48dbt1~4Kp2 RBSU&NO*]"=`Xiuj@)L'ֆ]JJUȫP159xRZ[j@bjvRQmi{vPHv*5'e1IXSrP wZGO+%դX[ ̶V1Yc*1!akgin0T+*e2x&hdd`qaSdGبȿa<>);Mu}om8Р.-P}?MhX٤_wr^T$e>i)5RNdi@nr'} n'mO3sT[CHq}Jt3:V~k.ˌi➺)*~Z\ ʆ87{kXTNkE⑓\tlL* Mڞ}vkSuK懌s}#[H_~_RT”9`ѽ10]W5|a^PPPPPPPPPPPPPPPPPPPPPPPPPPPPn7FْܖIR_8\@I#2hYtS{DAJ?P@JQ&t풢} ݎrO) M0jM  ;S\G.%s[AO[{KiSJQpKHcøRA [8zyZ6VraJ_Xvp}˝yQS4k9 nwz vS޻?^en#m@{V; i+ZNw+rIyV޻oND>&bm=ZHx_.k>:?zGNZpT) i  jf okQVԼg 0?o)nR$KiH7zICg]5ʘo%I!%.|~+]xdՑS%Na{܏ 7Y79EA޴.q9Ť"\0+ R93kvܖ;sU&C\U@C484ăpir$gI>>Ͷ JsS ǷϺɡސ{TTo2lVa.SEg]Fxt9}[ iMD1%\$)9I8USSw%o8XpcVvOrJ`ה'r# \3`)\n8NFSڝPƹ 8 d8w;YZ"n~*jm,ܕAgrĒǠV9lw;$ _o~HqQ2w rNBFuTl,)k Msa aTJ @_l͖@% 0{z[>)^x)Qpղ,-&#ZF1X '-E\c2Lwz(ҙu.* iuiySCg`NۃmVV pG=DZ#At\aZ얕qV]``$1r^I4sWJ0L8mI#p҇8} Qacv폲vA TyhGEPǎA؏|ĭ 옐N+6OZ۩1sM):j4s_rlkru%!%%9ݞ9j[_ARgִiyin Hu51؃|pp4w~03EŒ͸T-(Q%I8XYS-䆞Ĵ@c[LH mg/d oq*&S pV77% 7ad7:1*6K2gH%X)fSR B!.JԏIJVr:C}[=9>vk7r[B|x>mvc t#{Cۏl;#m nmnG*9uֽ86kʃ]RLwX}>Tzs HY99 w7M㝧c7UE6quu.anwiXFY:C5~B8%~NMIPڀ㆜{ ͈IcG N%StL})?z -pU:ZXs];oD(>ݑqںl۟Zβ?ӰOT8rVq{Užc x6\3CI *Hickgv<~T᪼JE-qn[}k+ȨkSP5?ԭIKm6V-ƶ:O >h+[np FʴFO3>~Rjk-t#h szFʍow_::ZuZZ"rcV1{\ W+\!sGjx} -Li mc)P]}"v[XP$(;>1_|eHoh 5K%7%.8렄E [km f{t7N[ -EGJWϰ9Ry|{&{%jZ0H+K4j'q;@[[\( }+,^к@hUtCj9WK(>ϦV*I$**%ޏ8 |/s@ - ->X 㫫:.׊toY =#{WP7u{VVr̼\ <T8I#qء$w|Ӹnk]^]4jq5c]U,cX4Hf';i+XEtܦûKыBHQ)$WtS?Quvf0u7A~7un tdQVZ~ѩ8~uWvRVMSfcLk#iHK yNqAU_lΙ_ =8o7aնrWqwM!n]iݼ Zr?qӧ] ?VG {QcZ Q< I9a.ezؕDmIuMz';NpyN)F՚RRKC8!$, H9E\wjhU4Qv25#ׁZsò}W80lwQR1RVǨީ4K .7Igu[yՕ-c$O]y3T8ܗI?$RtTͧE CZ;&:7,b׶SO+3 H jO0UM_tL}{g,&T%+ܢW*JH&z?O(D2Kyg#Խ1ҷ{YFi[֑Igߏuyyћpl$3qU; G 8p~FWAskdc?Y$dvSJIMeI>@WmLtB@>5`|-e I#!:Z7M'h 3|`nwLkÂێmZV dZw˜c8QIwq(`]cs-n)IQ)m!`Bw?QVJjpVV@'޵ٝ[IV>rCGlB֝ۚ^`kf59_jۭۜeFQO}XsPA_`kN֐~uzv3`vq'?D4>`B[S[PG}D|ǎ?E?]C{l}HHl6!@p}V4zrH' sSl icNpY-%1fcSܟvɦ1a4Ѷ7}r<󌑃@I=Ԕ75[ﺉ&V<6cnUSʌT1\?1 p+i-#es7T}Rq)(\6NҔ_4%3,! |9<8yfogV*)_BYZ݂m>8V}闈?e9&R,zdzTnwc8vy[jFw9Bsw(o² A |VPʩ[RuH8 ˾:qJceA_ ZTy#VV $P,|ҳRnRO@h%EƇvUFBc$YwrKvY]&h?7*S,DmQOYJdc.<yR8 :zki+@J|T˥.WkO ev"p)$-X*gd q<ҬY3'zO"O<xc s4߱ֈ^JSNd`:/$'#4IJ29Si" O5&!qKb J$ezT2S)3IIE6qk{-MqRI8zBMX8OSg; [ e9Jx jd9%HPwSCdc$d+2umm͠; \WyŽv=KW%!ARyޮU;^F#o@ 2g-7&aBCni|$)<[.r='+%)m!$+5u͂,+llc[p߹TՕeӲcP-I^=+YUOtuu΀,R]1C"hޮ?QgDj28㱮EQ@iߒqs/R՘ҝYZӪnXTu5;rz; c(h~K=~1unٍ!A[rÞ?u?!_i}VJ-NOZ]E<'#U?kYe; "(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(BΫ3L˿,uW4:vK: F=a.w]))]SRCqR֚vAr׋lT-c>4)^88ȪQ\5,"Zd#>bxF(׹uqe SY@W &d^nS?OaH68 } NxW/EvպIl.Is[f,p"[wXmJpx>aTz -,0 ѻFw ג;ftErMwh&6; uMl=Ov+-4:2:]%솔d6++`j@A9-o麙s7|{&[xX|QIk[,č\Ank-.sF2P n:G\@#q[, J0%_=1XbJHR'SQҐXC%vIt}Sܜ+Sg2ޢ Wq[ue q>=_ZLc)H Fqx]먧;p8svS6؃v6\7ӹiGnDo=…!8䶤pq޸Gܨ2g'H#a[9d=\E*$]mDAI WQON30.AR:VC #$c"pr>Tw›:G|KQ[]&iՀIJ*cWQ;~[h{ZHդKsq)*0 {=9kU;X,>)Ka9mRp1).-#0=7k-Ɨ6џnT YETg,hIp'#煿RXW6{2YN(RyIEkTPVKE00w RwBVn o-M?%j;@Qq{qdl1Lsmy,>?h)?Ftcm?܉9o^^mwKXB\sYI@JNԺ%d&P]vj)!6ɣ jv~eR-7Ht\]31F[-M9:cqt5^tj(7}T!i%?R1 k;_wJ=JzkGp MMV>0p}UxuJr2l\.8*[:TM/axkp2clwLtPuJƗ Jxe|d ?KOGڊHP8 ؃TFcarԽ/+D9|lX{)Zneu)Sޡp^c c( ;K$'z0{EmOQ @O^[q jUB>a=vO5qMR:lgA-#qSNŔJJl*ҿg*Ή湇! k\ӌ<1}YzՃT iվ@'UMN_,79kŪ}hҴAx[CpLÇ1>VáSD AڢϦ:LfoIܰq'|?J{+}]dtq9bC' BΣ6GCs1Oº::ix+cMBUe%MHRN9 ]|at _ޜgS&kɎl-?֪7Euک/ٿ#@#AymIHw[U'[Ti=D,]:["\4`K$iWH'Œ}3Y) p8Rv{gޗivsK̐N:ٵ*`:~r+w& *h!o#I/nF1>V͕`򙤾ؘmj6W` ҟ};OqeX Kg4Rpe-)N旎"sN)e"-gڶa1SyCl%dXyI$v53ggƢ6LdH.IODEEu7P; .)Jl O֗7Wul=Z4\V$Ž ʰr7Ye2Vi,1 ַ;kHmfrh!9 q)Knj8RTg*r 4tX"Tg$[ßZ2_Ex2!Si_TOںno_{X ,p-knOeYH# gؓ.|lё`wZԑ궓+8m}! vcx H9=(o5nspVzfOnۄsQ^ Ib;-HT;VëNVS:KcCcakr7M}憺 ;!iǶ>UA&ێzoܕq\ӌGw+`Z!2\[F'mGB͖Ւ0[S7C@'e`poW`KLϪ4)*II'IW, iݥÂl n:3v" פ;?tLul"I@n#V>M᥻3sȗi3.&}՗D洳e.qu(!CM)|jN/ʖ˓%6YNqEhģuu3ria8]L *J]=Ջu(H>a+TKDZ;+UuSh%R;l[Vi\46TGK9U$}ՄhD|k1JRh@;v82 gkOee阚p)DW~1W.EHmEQGNTXڭ۬)PTOTwSRSS9g1F;? fW+oĠ 6Oڢ˲ ˀgf$n]"ǐCR_u1J@ .j qHotɥ%Dx>H@BXۍ)X=—%$4QO0nV;<ȧ!0[qu* >Ҥ;p"9Jv fKY8 } !XHaT^C]K &35ˍ-vp8I1c%@҆!ɰNRqM tsi̤{HO'4G;SX@pdU3%JVՂnHZ зi[+Q֘nۀK@YTL+o]CRB#sVՌWjiFxkk^@乧=n*r cyݪOYUhppWqxp?q20;ʼX󃯚v.mrUtm_ 8'??~:P-dS pbΑ}3 .=m#&Cd/u٫BBBBBBBBBBBBBBBBBBBBBBBBBBBB{o߆ٺl[Z\Oy -M粈 fRxaeۣh+ig \2c9_Z:ӣc|sm_k䙲\ⲥ-G$Mhoys<8I'$Wdk#` D{ͦ+*^UԬ3(U76!ڣloG,3ź8=rvr7(ZVmlTZx{xm#a䒬tN̜'=o,%摺F3|hoW:-Fe _bxkH&&tWA].!9:b-.JÇ#PyKt:S`::3V*] vw}2HoF}C-R]+̦6?K}]"6`/**x#*Zb+fF\Ya.S-*[Ksrv?%53^7 q؂ˊKi>I#%9s~R &U4r~w jesf5uN6'#jJ7E!k~L2SLcQ-񮰝鶟_(8H'Q{WRMK]s]YҴ/$dmy SSA_e6X3Znj;L4~X-$-^8H5@>>u>U; z񥁿a\V;xeȺR Ⱥϙ:vuǔ@[FGͨ<$ oᢳ@4՗*#yM%RG!@SZ 4T1ItVv7qo/2p'm9]#:w'NM%T2X%HOuG}#=<ψӗYN$N>\]uyQb=w{vILZ`pYsn*^GluT $f}>V Ђm|g^rUl>Y@8^M ;e*I2uKV-l!*9RBYYI(jj5td5 #88 UAP:*i=?Uy\'Ү/$GMT.3R{NI;Gl N8]>%gj.h!jgSm$x J[iەΏح̒$ ela=87#m' d-dF*+EƠi?4 }[{ +b˗ɋ-)%Y'nn5Qbw?VK85U͐̔ q=5'IrI< g1'CP۹O5%fccd?+[d;5(ӋYVR QgSM୓5K[\T-c'AOڸ}Gc].ؤ#+Jd8lg+lƒ`v!q \{bʩQ2+9l89HK^ZuV#iX 9G2!{b3w=BEV75{oljmQOy]OQ)ju-$.SeNޞO(-s1J4b@J'bjqhlPTj֗m +dWN8퀞\QZ('ryX]1HO!H:𢣌Sϯ( hTϚsK pӔ:PWӎjjG;aMD|)U1R6!d*uA&pC9@ZI9ԡx<)T)"đf u#޽Z8M/$'e=a[zn99ʔGi89 G]_*ZVsJ V=SV; !T(N,5)yq' )P=]O0Cuxϩ4ܭi %[?nEVEy?tUsr4ꕁՋkvaE-X v&TIK+[!uqZ˄djJٹEz:;cxeKt9b9S+&:]. tx5->Md4WPt:rdW" ʳp@>GzIc~b龘7I}AeEu}}JH<)==1Xo1I;;-{]Ӵ $}>Mvwf_77T<֗<睆;rNF\仆;Ѧ5 .%T%]Sg+U*+Ce' mhǧ~T:ҦI"h ~;Ԛ*ͪ(l!c;}ntiu81ϿlA\wS>zoX?RHXm֧DT>aUxc cFv)Х 1>W_&5gOJQ j>^1AB]m@_i.|[s=ܽ!n i\}p쇚_)/+ǰ\}Mmm|mq⶗za0DqnTEZCۻiҤm ۰sǿO欞Xe|LŭpվL.Ӷьc8Ҫ^ :oG`2 l aX!{`C]ŠO/rG:Ηcۃ쪗lc\4J~޵AStzRy[I$Zp:ϩp4c`ZV{e(5o?D]zsҵ,O1vCzeO!ryȧz~[$%<1?. Ɛ]y)z2f2l|vvkW-`^$a8Eo${cfVKj Z7.!p9粖kdw;n}WrȷTڶ/J\OԽLC-:F8cw7+V"c ^>Gk'o[ '0%~j*-Լ-J `TI?OfNWn6ߧqޠȒ7p#l斸d]]+=hNjNu%M:%GI5/SG]o|'WHmKr@4d8w8Ufg' s?%A~:F+SuFIrTˑP;3G`+E:wJ ;rG!kb84#,iܮ}x}_v}rV9+mrސ]Nܖ/ޢ1y2n0+g\g7h?<JM{c:ffv5^ T{}};V 3u9ovڞ̍`3؅m^9E%s\H1F@=@٨-K@B$Ĕ )PQ#i;W٫4\mt1KH-Yklz,Ҷ * sT6 KA%9?0D>G3 XtMCn]yx!)7<,ng!}A Fb{HwS ߅,W[l^ܐI'q)۞ET-Ͱ;~Cyk i^ J~- L3 5gotðA%$ÁRMOiY o($7gc`!8w=d'Yj )Āk~K>5U)o 9)3BӈX#xRGpy)-ŋ $Cb\ ,9ǃYmU6G?p~LOc]7u .^TP d'> ap;ge-Z7o'vFgj(~{|$R 2T\?n23S0QWײGD v78FO;BW1hs ``KnXHIlI'梭zȆq;~%3(CR.%spGJA*^ C%5_3n[BgRR +tKni]kHdۣ7)JB`* l)5#liTE@}@5)cV:L3[ҒRx?ӽ` =6VFV''9] 14Hn;񑚈3TO*"[m *;](J“j<Zg5kj潣#U}vuc߿s m@8+KnUźs="1{FO+mtJX5C}xVSN;(ӑa!%+%>޴cƼs {&.[#";RНb78otSP!螗vڇUȱxyc ݿ_g*+ g7药 Lz]'$\Z?eMu6s}S1, ?R8 8hnq*'_5vC|@>Zz~H0qs@YN1LG |NjH~!L}$l>TD!+CA(Zvb$I6'D4DQmfWcihc*? sv_Im_o:k3(.,-vpGqs_Zds3V'ϼ\߷4 婦B } sH :(l\RP>pݪJag!@r\]y[ԝ$g1~=.ҠvmGjaea_J95ZpV&xܧ;jwݷ<Ŵz)? ߂Q$#M)6iUu)8ƪM8*e t>sX=tl(Z '`[&91d)$vSK$*J)c^{l'/9;Rt/wH\!phNWt~zN)kz^P^xmx6ieXY/:ӑ&k!#գhl)'*Xu %յǪNn[SM$?>N€{T6Q Fq{AF9\ߴGBXXIƒ~5M|mƺIhmҰ</HVM_9q`حqM\_NpGvkޜt6nP.#{|d`/<[mFH]Uؽ%֔JH"|XQ)<0ömyTE6%%a8kim/JNā*QtWN|;=,҈W>c_w|tŒ;A'#eqWxrtC-㯋9<;G_`T>FJq}t5=E!/gnyqv[Ul/}^ca688v][ea}v )i2R!WlL9p{R48lܫ+MaVQސ}4a' ^kX`]&Vu*V鉏u%6HVw }^>Wӽ`D ,l$/ w mP2>WumRT{H)Jsn-UG䕇TR\nqyW:7eӷ8 58!M2רw_8/\4;.cU: À{c`-z+tLя*&֘21Z#NݩI2|ztWhOF!}O<-3s#U<É lv;A8RpHOi]AB >vq;*]ף+)#%qW֍Ԗ*-szG}?lk3.watv{lEN3*R᥮ .҂svs[B|쫓IlG l#YR¦/9$#vW uBړ )Nł~N}7#Z*a oUZ㺬XI_nDmZZ$cirpy$E,=u`V-e<W ϺomL+u -G?Q?={3N;;$f׻qP7?‡_v!'g; `g9ƣ4f"Zz,6x>]G;XfasU7<8C 217 S䑜{*C"X5Ds@GYtA棼ӊ l;l}8:ޞGX.n@?*m熒N˖^3I晿 ETAD^=.0?:\XtxmST5w|- V$Jy1!2SI'jN*Om\*sZ솑#vCr1Ӿk]WO`sQzPZu~, I]- GZ[*E]gC+s1Ů##l}YnVj]KXH?jNjqxr R]rTˮ/UJ9ĹO[m!`dcR]Y Uc1گ[gSgTFƿ3cbsvH>Gum ӟVKUJcp~lK{ JI;Bd`f+LcIL:q؀rO /}ytZ`55N=ˢ\G]m1s0S"Sםe*ow[Ǎoߨz˥<}5G<Ov6>YGJF0pTM$ ~Nli}a6p!Ăk~'% sF8ę9p="|{:N1.h!Zz+rޟ=%4z[E7;W귄Vǟtd8IA B{sWޅzitϫ@ kXd\Xv0+צY D$O c|㍖zNj9v/ `Gu&r7)*!-y8$aޡ: mTIOn02@{66>=`V};}#$5m{kʢQ4rN ZD{2sԢ%8ڴLjOnԲ{}tMh 7&W>UۥrSR\ַ@}U]AТHT?+9vկ4[mg7H6q^XSÔ-GhmG NG=(`c> ݯqǖOVتO^2)etnևVqvbN:rEMZ\)D m}È`q vHwaѵ{aWL$p_,.nZ&]dSR'dgK@#V[.=W̠M $3a$ ]2N;:ӭ.>>iGҹlGe$kୌM-E@}7 sW`e?FM0qӟ(,ҽ8e41ԧ#(D$RqVLq8<=p.B2{0?29j-v@'u齄qH tSAQ{`Poa*f벜Jsn Z|e ŎK*Oj $'rstE16`sjќu#BAv,>'{:E[O I`ܡ5mA:p kc$ <.qs$i ƍ*-*R{}u44mk,T'%Odn md.~gesv *3p>O J@Vחy[P:qh;gJ.%L/ T-.qJ1j8ea >84SߟW1Xe T*=#/+9LR2䤛((qqS1 H*͆5RP;ɥjch`تKqa#i >sx*52!)[?5Qr#ԛ!աJP9g)%m\Jt\ڮƛTŨ$eV, _6צU1WjXr-h{gdڞ] HZPTn[,r3S%7h%wYҽ#aRIp@Ӻ _7' )NJqI=/^ Gm+')ղXĸk>{"h%h9j:v (e Ţʾg#]-iL`W^7<XMLeVt)NڤH[ůc[6ɂl]1cu,Z>x\aiſ Nqrі7H|rNWr_֗շ1 0ټ?wכ]樹`9$G`CjG 6p ${ZSFh{s\uG>"xkE\F20Gk}_>[+W8Ѱm?h=uNJ-SkSk|tH&I`#a\fHJ]cֻԗIppoꖤclWo_Y TչkPPPPPPPPPPPPPPPPPPPPPPPPPPPPzG}sV/ ޺[H{!-$X+?H)սAC=Hiη g$d| ػRQ[MU VW kN~!5%?ʠpGpU:|NJMaIuaJ>p;5( X/cu* M,aIm$d$IU7˅E-rɘ;wt?MC@V{JaQRDޢ@֜B Ժ֫A wC3dmVO? 5w3 VF!OH2TIב4ǨVx-vm=@'Yn91́ H |};_Z+SQφ-!Gޥ_(l0[c*]А1uOXZod*y!~9b_ӿs~jA=%^%Ydכ{=CZ}C|W|Kj* n Q]I\R3q{i,ԕV e߃as~rVn+GO/-a*1 ,B_' A) Oj;-up1JF8[PJ˴s4Vs.iHW(32B$+aEts`;:H;+Dqf;& e<)aҕySL3ò hv*Y.Bǒ9j 8A㌂=UIwzx°&\h30n3ePڸ= )Ko~SX)|D>98bF7/`5܁~Sl S3hz^AN@J_=lT1߽7trJI;*n۩Ҁƍ/ԚsUhkJ=N(e”ҴJ檗H)JS$뤺&}K4d9''^:NjRjqR]+eӗ] b-JqEչoV3ǓcYK<U9ĘcF@q!dަ>(#f9S|E8JwsZp2/d)dvCTԾ@TmKF~`{iM䶡it@@#dڮ `ǶxW^Kiwmwa ͂S}#@WĚk$W"zm>Zz] Uޘ}ؼ1=vp=x+FGܣ[v\WVϠUpB25XY¤RZq @~vRg@)3UTt|u#m,M2;{*,`X`{uFKb7}#{Ͷ{!c^QuvC$m8#-;!aoE6Xp~m3rLiJAHJ Ss$Ť6?#ASRn̶8Qǽ )@`(qN#i'͛HΙػ];Օ8?*A8)W-w7*Ad5Gr0A-Uh$)0Ȉtr~ke>Vjt»4&gQn]m$;d28[g-u問9.!}^ eEEԞiel]5 UvC>i1iu.$()O?NXHf= qApnv N9 [@RAx'3Il'EnA+ہM&č :GOi&^R\HG5mZN%/qM&(:`Xq5HDڕrIj]3EN[$gsW1“[Pg[jʅpLJuvwJPEmnÖRZ@cFA[V;InKMR@╪s4 @tNJF 07-p^B7Q0 Ĺ;S?V8 fX4ϦH=) jmzQ.-e U-Hcͤ˕/)p7& X\qU8*yqctPVx“i=c?1ImT=hgVQZ 3!沯ѿK 7-+C2?A )tįܑʾci}3;O\"Rc\ZeKà}`d ct>Kܸ.p;_}M.pU3˙ ZYXޟv ym ~ݳS]خu.{xoU^{S.JmeiRxTQ&Ǩ)A O$.q[sPMgiGtpCdl~[#n.tꘪYz^u--uLs?+mBVyvP#Q>FXƬq-mI'޴0g=BzIH籪UZX\~_g m^*SFC y+Oۊ- d` #Hn;0whxNU^]B9xWJH&`SezILx*ir|!?*~7ouɬފ}W\iG5ž(YM4J{gn2 | ݽ yrx˜5 G YT] xJmhRm P r[GN̩8n젫qK+E {IqۺbK# TFozJx"E6Âr}ڣoX!on/ )6;qCnl;#@V v'wjMsZS&'$H{s^QRI57UĹ9$$'Vֆ8cl050; =_i7JOñIL4bZp|6S[ӚtX}AgM Z>;wz_X2_^MetEtnǺtW螡u 5fw*Tk.DFITŅ ˡ|PqIqSy!v[&#sK78-:AZ êڋ.hs*OITɥP%aN_;0b;2M[+=O.ָkr3%EM 7wmF2OOUe2}7im5+p8T8< ` ~'WXۅʹwJs;vd]wQ>,_QXp8_״+@;8~ufn{/>Gc2BKIg8};k[mmK9qð23N׺-ݫ/0-Cm6O =]qr(3Q`+-,a~Bҧ[ʃnY'$++0w[+Q#Ҥ(%R hZ8NBG;XkF;ܒva`ets}:z{P޶c0 No3Ykpah<c'gW6w|mj#H!kC 9jYN(Z$w⚹dN京}KM X#(#.+iB7e?jŮ<>嫜IVMp8J(~kFRX(r}%$R eT&Mb wV.NDuLD/%8=mcm[|¡7JF=whKpT6]id)jާl$e]EgRT-WPIڔ-0Gu)ʽǏ%@mnܕ5rdtwAmorw-aWTׇw bT2-0Z}Q$`\o~\rOnowR=(-j4cpLJxCAXԼ3tF:XG6 kO]ʫ:yi]Hdԗb=Ԩ8{ʹE-+a&gg9Tz?P^i) ͡mRs&8C]-YDs t(՚VrN;YIBJr4ID[ԍ ˰RqJ;hz"!Y ><sI.95`arlJ\)F QYSM9I$S;W+üo׌<.96IwDI`&ys ϶}0W?Eb9܅ ٮQ\tCZA}3%~ĀNmyq l? |(Q67a;*R#m>uU!}E5z1G9Z}D܌Kyn9n;==⥶p~T/CSK8ʔT?UOpisaۺ_ӵ8+OW:LŖaZʕl9 H܌Ď=WYYM_B?c?^}`){6eM^T6y>$ W$Wo"֗Yn2_N{xp>VYN]$9wL'9x]Êj)$y nxD8%v 6 Nz%,4~$JRa!D;+Yg0I)5H*@8NpsZ lsxG+TTKN^Ս: A Ϟ)7W6 "y#{+/I MKѾW_{m 0zgoZBNI]Cs{} ~eO}tv݇HZ?~Xɯ""""""""""""""""""""""""""""/#JuZN9&664+oI tk )iޱ炍c;uS:Se};qٚ߸۟ln;u%I|4v{udM18=e4M`}m[iRd8w)n?xWZY=[(ii15k'.9p݀ 7UT6TVΒCGȝ2]U:5-1[jb0/[P'<+Nݮ  Acs\܌s:#Q 覺gp7f 3n YR0<$ o\tgM[ d,?CMG9ݫTX\W˻Y]y6[%?4g >Jۊ7԰$m8er*ךJ c㕼.~+E* 12/H^ݶ 4 ڕ(cWZ7Q["ŭ_x> cۣ2\ysnn)CDɯaM'MAs.n@xTSN=~Wxܾe1m+Q#${f>`ʋKuNo2V;I/)C.Au)+i{vֲuG9\g )NK+B~ߊ{ +w!0d \[XBqu9ah9OX$H`"Vc>N@pөrJCOu6IVGmA%Lyh$ Ce9w u]\R-%H*}PjUD9 1FrR\۵V+ՑE-J-\T@=U,z_scA4<u-4gK O\Wxtֳ6cg}{Z?FVn?whv'V.APg߆ 7 ֩.v҄)۟sz^t?zZյy94m=ۨxeu&"bWj~B7Kɘ׍B{R+i$z2~?TS}RJjRe(;F3Pe,en]'N\z~e6\)VrGjQtˏhW w..992:8E?H+V>UX8駔\˝Yd:W6͂f 5s}aq݀ƾU8n?eru/[E)CE3s$:TP!BHW+k%׫Q nn43 VxյT[.|$tF9`7!}`HY]7i1f].;~Vґ ;v+&7IKѕ='3jhlΖB4AK .pzTyS0Qͳ Ys|XfJ܇ _5Ԁw*} =[6܏riĜr»O5ju d[`9! Ubݖ(9^8.h${rQ~(:"Ы Ju )8?^1{VU%+d66q۔o T-8ۏZSw)M~g< jZܸVXhXѷd]bVk_dZ- ; J 6R^j]je$텳-+LiVozjw&MS#2LmC%/1s:rZi0 g 0{Du >L5]7wЗ;*6mvxN>]DgJx%ti!4񽀴:^}øϸUmYK[rߨQj @ee:ŵ*z}=sZI䴏w~LCp̝Uvїe1m.# Vڏ Tjtc{O)C`܎p?!@ #J Y@Y)X[f@ ޒtrS R7$RAߨ AmEHAHV^&4/qj*朹+rXO*V;Cy{|"i|pO8FS|'ppT%!+Wpx#ާj-S7.- e EZOڞZ2q&R!"3_A:5xk͊b@IBw5՝/ac1il0q~Uʾ%[BcWݨ3שQ%ZeEaL('=Ӿ*EYve h|{II1 ډ[R/+'~խ<  [\A{{w~^gĿi4fBܿ? ƒLtiR|tnSκK w'uJ莚 y+uܜ,+I2jcl>s:Q\#>²?޾n}PKRfsZ8a+?Wy8>JuiN6'$|Tc 79u#'wT}QeK)ӟADiWcK}Ლ7[=>2~a3#[69BjDy ¢uwPOWci  _r|BZ[k=Cu2T7rGz꾴|*4)wP֮62%?e&sV+@u2 ±Q aD]W+ MQˆXbqħRY:Z.L妖IǃڢS8qp]ᵈ&;uޱ|Ejd[m13ЯكcF&/]3c_=++"""""""""""""""""""""""""""""/j]z7zi%Af+khQQ AW;i/zz>N A(`s!K˝,q q8}Gr l،r~%|L&ߐUx5ʎ'Rx1gGLpҖ›V)90bv.f-&٬=)+rFۢrG 頬'Oo}i9EUsc r@q#sZĸ壩WBpgjeN!Ƙy`:Q QH޹966@?l9\X@'R5+URAIc=2=<߫@ѶY :Awlr+iNa|w8N6KLiVlۭr?Tcu 2cS{Vtm+$pw׷=TݲRvgU垧A{a-RܧyۤɎ%F>A{|M$nwl>ONX[G}Ui馊rvP ur_e>ɽIC(W&;n}%Ǟ%-YlS@Q˨+?QPRWou;fwHŒ] V@[[3)~*g< lWbW/'HZ'hFUu(qqyxT[Lh'k}հoQ@'}Av)PsGp9-sN Ow=Cfnwt;Ll8~]D` N<!}TPؚZZ$$e,Ѷ3YhN2~OʲtKtS-Q/RLJe,@QJ`8}3`]iܛMX5jl2?FO?dqU)2CƠ{ }7U.\,W ^S8[qq]K|4·Oh쪛p"彰)?J~Q'  ^1xY6U\ %o$wӿp箎-ʺ9at<5Kc8$0a۾vT^txK}{7+܄ 8@4 g7~he?_l|m}K$G8c41TPN n48)gdgU3cvw's+5cs;w>D.+`wdWm_jeP7 <`'-+i ZT3xVp2Ch3Vc.8^{-RLndyؗBmHQBRrb;T]h0ٚ[#c;Z7KbH$4E)#2r,"t'7K)KjR'8 PNpqgS,O69f5 Iv$c}3yCS/Vy$aNy'r7U]8;նٖǘc F2ܸm9/Ϗ{38 f؊T6.Tӫ!1q;9-FU>yv?깍˘QY [0 Ok>ԋrLJ: uK\RER^1یcq>ED6PlB{HMsd S)H8OiO9rJY SBC6TÅY ՊUC,L \9M)bYvUkN8>M03-q,$؊!! rjIRH̰dc%,Ixݖ#xx ) 5 ӫtڊ¯RHn<*#rA2x53J핂qZd|G4VŭCa.H \9Zz`ڍP;)ncJqH`c'VT1+!\@?NZ8eR辖LL% ry}gEtRED֊3HQ;3^^.ƙI-q>ˇɍ5ū?+wKutQ)~m[}K q뺛2^yݞ&u4WzFzCR2S+=|fAʶ)-3O|zloֲrTM|pߕpS$*}VJ֬ޖdg*;[:Q2%FloXl)$g~Α {ʧ1.YIF*p2=s47r͖ %{GeOqI O޵UE;; ~^ѩ[#kR'qi*KSqZmi?\K8>o;ieߤZz%DW |r@to{Mihw];r?m##~9=2CyըJ9'k KJbl1?EBqJ\Il =!!!!!!!!!!!!!!!!!!!!!!!!!!!!!A|Lua^יLkr!_:KTɯo >Z>l8X^? =[ej~MIXݸ\^sb4FrrTO `&E-kRHJVP1??ܑ/AMD9b-H?ք:8ET<2ӊSH2Hk%ѽJ[r.2m.#E /~qZp8|jh&fMd_/pJNRSpIkme$Grpv5"D׍掍o֍OthrU?.+lyWk|)Is|[EQnz0 @7bFoTԵ cw-a]S\ga[Х48;CAWF׌x->w[jZM#}~B1/?!*T U |sݻ '9 >JZ.+ K%j{H j{;\[38b+ ;IRFge9XVŷ\c!;)){Zc\NȜuOM6*7ˉ'f}UVCk-N a L,A9ޫ4@lr })'[ʋnlԔ4NQj8 O$zJ)䕰D59rx 6^ \$_a܉-mCjP8)P= Jω)CH ؂hpu0餵-gĐaO%M )%IyR!}rƱj,;plH5REWJf u޴ʹa'7fލ ,fHur# R{n$råTQg%e9yaPtǃ4ԷAvU>p0 nL LYz:sciκLK%Hlo)xs৅uc0Y)k\rx㏩ euXX3\>{ gGh~ )u>4Ƌ9Tg~ E@xg eGIIXQc @touն*Q{CGlU$*ܤcկLD+QvNBQ/lܓh.irVcP *38EXJh:Z9qgsiMKu#;dO:U^6jl{kH ldHgp;K*5%]]U`uDrMy ʎZpӿ]ڏǩ6'꥾ud-jڇ%%( NH ]c\GBYq>\`cc <Ku *]È5:l1;ۥs\_I'"Ht;meȭ('>iY$a; ͧ{4rU^:U?GP[+‚y͑% H ƋI[ylw%KĂ xW$Tv.1pØx9P[.ߩ]ge- aG%( )oq;FZ̯M{ XltPO4qI$~G~CQ<É܇A kޠLͧc{׀pr׍M F?w [5%+À%߸I-p?}Ga$V'qn09R{*ǒuj;RJG-$2G!V112BZq91XlR։0ymğ'+xX$iz*72j@{ z )\[p5v ~˚-$) kHR;Jkr5].GjVzh[]MS;'5OGQ03/lFS.'Ujffz0͹6[èQ*MP/:P0HU>V-2ڲ x>CV6gVָ !9v.8vWw ҥw^Oq?Utu|,<8{:==M,Nh7['!9W;؞dZ1? ʋ*Z{y5M؈C#~2pwޔ/m֘q%՗1`C#+j]!o|`^i-+*]aZ\W)0 ޲G~*vD@hvnܐKtp Q9)C&nȶKd)K݆K,Pl-${]OG]E e#?: a )*y5-l]:6`#vI\ַpm[)gl6p!9R?4F@m33GZKP3s!Km( +|Іxc-# J_w4rC>umA#9'l~t $ԇ6QRQ3e)0.?0[ }u >cYg{ rpᝓ-25hvbRXFv=s8ngI9]'۶6 86"3z='Vy=x}:u&!o7gpJĘrWIhr1o&_`XpSzSpTV:rRަ&;eIJ6Was*>0x*UBeJDRqy *KYڝvuHN"Bրs+{C643z0P!8?j?ef_p>rT{S+Vx^^0RHˎ鎞|ۘCEˉ݃VZxٖUIqt<1-J|T乁8۸S?}GUCQ4`nݷ9e]-81LCqN/d_cfh^nH;qAKenSѢ^g%G=uT'ߧe[RG%/&}Bӹ$U7TDaqFv4 Ǖa@MHcbfLur-Jݭw~!*Jhk<:@VM77ӏŞ-)}LpwΣk:oRb#%$Gľ `hnyInN6P9yUbJ~ZN%t0;-`Ӆ)ܞZH<'zJ9Q).ݜԋA#e/L5jvJ6g5"toH@Sm+q[DA?{6_Zm?z`mƋ!ĹY>_xHQ;XY7|~ .=][u[Qq3tDlGGءS?ҸCgVB2i?K SZVu8l?O*ƫ[emu&Jm'}| xXhuVgP2 ;=GM}_4J"""""""""""""""""""""""""""""/A ksUx^onBVq:>k[sWWݪx" 2绂F_W`[]]DpŢ6 4\}Oh==pV?Rx2.tf5Qc5=!,^TH 8H'$OڣL ]5OMS@K&N jܟ{I\t#˚u,XKEC3 Rӝd83+ZȄl/ob?^{0uaYۜRĆ68Jp<4QY;%5FI)O'U(FD%y R ±wB+cR^iyYm TszpY+&@%Zeqa enI W{vFS78o:AUҤ8禽5l}5SLJ{ҔVw ޿EҺ˦pwRRp>=esC)۶:j{t!MˇS!RaxVAl/D֝^zW˥Ā;9fܝ8t vs܍e]Fpu o-jBV\r޵E|S2y$~k W~kٚb,6ʒ2ҮsZ>tu Ļz27\˦̻)_6rޕ= # u' g[zn3'S;5O*.#sK@~agzyVO"ʙIfV}la(}*9+\Uyng9Ah#VG|)+/UіD jȉ8 4kfVԍ-YO_ɴh}]զ6LrfZk *3IRNRjmLaMlt1H=`8lAcNc^0K#cg]=/-MT|`V~%v'OV04`18[tA* Oڠ ѷlثJuEYӢ^b2gʫ}7F,APQNYҕ[ve8 o1\}Euq|͑l N]4{ F%6TBTN=RGHVM%|c1F@q:G8v yS1|s t \e]c{*'j" FN3gd⢎!{eJ3_;ob%1#{+SYdnFHI1SvCSI]@о۴]f]CΉ^emIjqHBB̫5pxMVjhjh%Ź5mc%CPjBkN43}(Mޟ^|6E )'Ekjd䴑VyjہWlz MG # >6|V|w8H^y Bce--w5L `q8 II0ngpp}n2\n%. !B2?VQ2&ödtˬz!)R(jY ^.O\! +T;Tqެ%vɽ_#hoܟT:O:vۭ@pI9>ʬ\ :5LT0Q%ase5?9Ѱ҇,{ Uoѻk!elX!Fzqޤ#(q) NڒuFi+Gd(HOoI^oasܨ*HL8K긩$K!pBGH@=[g_ ^uCZ7Sz5Wc蒂qsSO,ol:N?OWkQ }BK0laiDtAI0(f{M*>*C\T%fA]Sb3Bo0m)b,5@;omZ]8ZrզFzqTݖ]q _'T/po gq-MSJqet$_h^i ܲ[: r>im1ӆ >}ָ9l쐍ckpB5f`3 >v5H+ZrKrRHZ\IN<eeS8aQ+"1_k4xn)AMR~JIj&W~tyg ~y q!֐8B~?1u,{?Bۥ ]?oTr f@X*"-%-HcNFTrt{vӯl{OqtRH=} Q_飙Ñ۱s\sH+D_b+s}?Q#mLi-+DO~Ҵ;KVʿir1_)~ҝc龰ԦJF-$PnNIs u+,U7Vrw'ҒRa\bEzT;wϸ|-}ھIK<g!/(1v “juTLt`e8V{Qs7WLU?#N,q ^Sw8Ti2](i#Ⓣ{g%Aa_gbw9;>.:EG,TNOOZ]R 'Ez:ܕ:vHYL;W;E0[psIq5ҝgàiQTx!| RSu|w$Ǿ=]cT$6}Gur1]em~\Kwvw}?Ut,Js?^l~Zu%ҬɌ"+jVB)\ʕO+ gISVƶwXǖUayܡo.vn jb9UPТYBl*w}ƪ`F-_I= &̜-,v [? &^ZOc:LN{/XxPuHu2Rs鷟#_y3ۢ`0׺_ZI~^8UhTPPPPPPPPPPPPPPPPPPPPPPPPPWBBB!}kJxHp?'W؃𿨺_ViB.-ĖåJ1i( USЉ$,kƣ1Ifeu;OrG[f?TU*&v \$mc<6vX_$olxnrDӌ7e1~@O$*YЛSB$Kh wΞ~kWFWtz'Cvܜq3V;ٝ{EUrq݃Fx]zcU@SV:BRTGRIVzd%'$5w8snܕsO|?i^66jL[tWI) Ԕ$vHϽHx4=%;mC58:rlQ3mf?;{vNh8%@V|]PyQժ$qrtV0 T=(ʵ WVߦ;Ss)cv\IRBul-D)gߚ6I(4ݸPRU_ ;ZΚ/G棓^B67O5B`?.b>a]/{ /Oc[%`6J3i-_[/Pn~Gc\Mi'nlv{#)7b]ܰN0CE`g9O_kN]NAAZ(qV\7Υ_^SiKY;>kϸ]%p8E+ndP2.&T=dv{V!k:V-z9 y.⊎gI 48;rh)|F9sq}ӽX7kRRprVˍUZa?Hܭ[)+ib>ZKbAR)Q(ۊ{v.10"Trቷg´((ێ*& <>m426*jBƾ7uǨڕ"!ay9OW^xckkmٔn䌎i9=uqDݷsZQ,"5JcϩN!I(rwY\^|): ilpс괱.+oYڬr2;t??T;^DRN)vO,)k?O|gi+)@!GiғÅ>uVLT_w1i'}FAخøm]]xȦX3 gJ;ܴjGrЫS9k{ObH/-S(Ka.xu-*USL6=1[X9X6 UZ ?H/˄|wKw[j=?bkUMڧi;q҆5Cc!hZdzJ%Di*FM>Al3!Vy-AWjf9j%q<!sUצ 2#2۪BgGBJTeA{UD|/Ʀ=$9{H#؂AVHp~|/͋8IT#=i19JE?{* JA S9`g!.K)A##7RamƤ/0:yS\m_YN +bWҤ]Y!)}uUHky!Q'=IeiZJXq9I~iRCe#pv+M{*:Pd!I$88;5!q^20] DY/)zm46>7MRqI8 \N,jev>!4AYg`sT2 *= MeN{p)6 @%*Os# )07*b)vD Bwޥ*-}6Y}P>Ķ|Zkfi[B K`i!' t7EjoK^1;8v=Pڹpi1y\ +USO-j9䀙O45ДPNj{( Z2UO.MQsXr)\ i̡$pG+qa꾅4uu1ޗ4؎~B*WyѰ<4+5Sd%V)\~UI4I\'$CNрd2[BR~89i~dnԩ0 1xRԱ(qLSѩ:1nTOFy*q-#%GuYN\֭WK BA$*98 >˹Mf1BʖQ3FcvLrt"nwZٔq)$o'+n̐Ú@'oh\Y3&'|֩M}o#I(ckX7}WBΞCqAJWRSuse/=?nlxOھ!k-,t>t9;+f-HA#V# o2.QPGM n >.x$nq\qYc)cs[V- Kޤ*E{{g$LO;/>ql=UKKP/j9K5`/ïCAڮ9NIJ_[>}[j@h/Y:+E;>Bj"B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(BK zaXJI>+ tܹI}}:_!.:-=id71$bДH.ppx~[D-5;:?;{}Ln*Xj[MԚ'y[\?zwz*k!I;U8ㅱD= *t뭡M/>TI+~>j۵F4_JcGzt^+GaR[#'wk|7:.{psGKsq qO>!7*]`~Eӿ=aON=? 6#?be]/-Cr.R p@E㍎K81|AQh$8aIǡz22q{kIٸ?sHduT$I/+<62?ڹ5jӨ={|W 8[ %LZZj&/)**#0ΒjP]'m&[a31<8Bj/5*-ܟ`⡧ڴM q)%ρcR)k]GtW#_6ԛǝ GmYm[?r,vlX-/WLtZRqWMHY <(& '*jS؜vb͇pI>ı ;H.v7*LYI-Ys=}V?5򣨧uFtM0\z#.Yv[e xzX7 1#p?m_wE X/G|NA)ɟ!h{O^!u$D6P(Zq}1{WG4ai pqnJi?iKz-cdG p\iC5磪zL#y-<'d9i+L.:&CiNXUŽm<d>U"br'YƀݞGi99Zx5&:۪ei]IR00kLu#Cids<Mvq#m8TN\1d83`dȅu"uR[BG<XZ]7VKϧ0[Ûq@\rӭ*,gߒ<%켐LJ}U3$UOGհ9]u5pH\bqwVc4RrSw>*㒮u/.8r6N'0M#*8FA7hZڒbOepMf&^by[ Hbפ9( W9YVǣJo-<>Zv]4!%KC#ڂ%Ę 3xK)V)' YJڲn'Hviko,$Gl~H;] ryP~;G+MSLm’RRpF0i 25b v 1 xsM4R %x-Ԥrv)5mRƵ"x,fmGC%h@wrq]Z.@ kZt3 )~RQ=&"];qeO0H2C8d*_ zMEG!CCOOQS :@I' Z9=ͱmrvKcI--f}Ap qOmN=?9Ec lJQ3Xu;9WfD ֬؟@6PSG![r.!ś)SR 1kkXճLkֽPKjr]k[|!O۷}.? ^E+"vOcW.[{'Pn75Bڒvj9΅~7GŽ10{+6a-1-B8FpsX/V[ucYN[1.Gs6Q.E`8g8-+V^n`"̨񘀟QQRlO޶5N]%cdtQDa\Y<S>H&[VwEǞ4?;{V@Q_QQh[?K6c-8NST 29q=\ aՄ/##5 &SqRqTje#j -}R~{TEUHF'拎DGL.''SK@Fb@y{Xc\6%%[+d稭CmX')ƗMI`nvQrNoary>kx R;{r"dHJee~f݌"Wzr vF<ꮞuΗ?#&T]fUؑ+Kd4l:G=]ٽT.- m;{gn.8ϲ/;sV0e]d;V $>)pGce,.fۘHI<|{VV#,@=޷R*ékq)%*mĐO۪G[F?_k`4AG cRfEu:6 ޛoFdO:J5ug<$$~I<˵lv{5! n} J! n ,TЕk-usf*`׵w\~-2Aby Tz-!IIT"_l==w&t #<2>]zzp@n?Ǫzw+Ŷ;l0`-IH V>洿[w{a+utt-C 3XZI'k#lgn)ݲA+$TC .0UriJNA8 Җ;prk8o*Իb^XE6_E-j8"'9FG dګ%8H6UIG7>)u9]j8Ca(q5  .`t$S%_PX9VqOiq#]G4aWWʗ{ivF\id. zV뺃akd-vfmtzX6s$GMQHF2p~nӄ/NWFG[%@m<~kz7EtvIی6e>TCZ9/իYz5,*?~tvKTT1@x$I{Ho*ԨpPIBusCgZoS9.:ԅ1Ci=q;ۍJaT Ny^-69K:KŇ[oOQ<5%\XFRTW)R<.]G%0xtAvK@M:)vhl`γiF̜ ZxȩYf}8?䮔G4u4}wL=?jDd$) 7E}Ǩm,m*zZx]U.9:Z}ӑQkҺb{GRQw(-ڡ`?|T^R);g!WqQR}՛8/jO#u]Ki8R{UvӪǿ+{tSQ7mk-',͸nQ42A.'?o oWkYOE$8et8leY 'VM-Et;1/mwS)*a¶+vgнGԔUW)tόzIny Clds@zվܢ$<ڹΏ@' |[KJ$9X] i, T >ʒ=V{]h!/8:^9[#s;]wNc[P7k4%FVE%91ZMKT$p8$Z1ؑ){]@E>H\$}OoM4- ܄Xm m<O)i%CipF@sKӰ;sTTҵL,|G3=l"l)8$ 1f\`ڥ}nARH OqecֹG#{bcG+BcR&\rJ1%4 ?8}#S>ieڢIHn$_}j/-򛌴`sN|4t.GH^{e~N!jBRK%#1$S'!ccZ( L7[H!8ܘK)l̜y %EnCKB!`=l |Pyٞ)ku48A!Uӣ(/f $Zr89dޓj7Yle2}u!-=BaG83SSMWQ5KlO%͔114ir1ߜ~{ӗ=7siFz WhWVA$AOe@랾ng@ŵȹ%CIp8sG_*CjZ%9'n>ղN'L[R^z~TQ-*HJ07}9OSI3X< M`d'Nokp5ǎsߚ4íPqn({LnKν1a Ĥa%J$~#tvLPpۋi]++iW)NOcwGڃ%l[,85-:H$q g+euۨqÌnF[DOR2$$~`4r5xdٓd!Ȓp8#-krc/cJ^9Feb vGKK!IJRl.u?1G|mg[M y"rIN8&tj/()`E*9R'3IC7r,-[bF)\{SݼSF!2#XCہ8#qPM Ӕ򚥮$aWR tG) 07S +nzU*w[`\$n?¢C]+\u@@|Ҟybom-NIHy5NN+V=!p8ӞnȋTY *(Gz_]Ѹə' ֳO#J]#"6ێy`n\##<*QY㭈ɰ*םtC۬.]uK+^1OQO7WQCmJ[[NOw;mTGm狔n"Ko-JpN{ROlkӲE|_oߒ&>Ik;\~0S4R:T(H 7dy|p~gYl8z}I ?}CVBȝpHY&A$wo~$FOtꞷtuqck&Z_9?־mw}>笴7mPv'ՖJ'bI#{ ڒ|&YeNUTNTs5@^?I䜹߹]=@d[?.6 Zc%iέ^teDP%> oeςֲRD1~U/A¯NIh6u][^wKsm!1In8?SR6w9¾FO#ǭW=.h> 1 ½S5;l̠d x­:f.+sAX۞Ĥ>* }MF\0 OߔǿOnTpv{>|V;;`iQe;~)#ʱ_6ԠsSV~aX 5{+gRz)" ݎ2 n|NxV;_95mfjAq@XUmQH58t=>-Q3M%نE$5+NqU_H[Ga/zZ|˵uhnƝr, VbRF`~"Zʉ=%GN]X VEoL:[Bk:jeY.nY;'>,tE$ij؛8;m$+V]{zTW 6.:U  [з^ޞM 9$q'.#8h;͞[B* CF6+cz|K]4/zL%<i֊[lNޢ57rvh'nOW N7$~*kLOD kO@R\iE`c(F|UlPE=%inFNTx㝾>Hv WD˵RL'g5"YdKd8k>p楓 MN@!`#ьҔq=r3p' .]Mʟ"[yhL]_t'MD[QSTk^Oq4ڶScd20ҒKt% sI@2 0w wTil) )nK$ά)lNH9p9 jίWByJ6MGpBb>_pqZ^ZZ~ 37.Н,k)[̅Mm8N2Vn0ò-YCKWkfOj{^E_Z[uZz% (+yRu8ZҶW8A9#ޝQԙ*ۦ-(DkNտY{S3PEu6jK)[EӔ=]1 Cs)NN6TĵYSڄ"%s36̧X TTn68sV~N[;h_UP26_HcAC #/-YO4Mz$p{%S:]qg%J'&PѲ&Z0jT%3ӕͭXRExN5 aB)fOZ:lf䤔öB:vu( SQ5[C).x ϓ#h<ePKn9{7+~;\i_BZ[iYbvRm#ZzM:ڐį;Ƶ`A8 J-Zh'ܗ }NwPiqu-Xb Q܂Mӕ1}m3ec׵9v?;+u+KA$~_[So =}i:To9>(RPNܢ>{%-'}>br,p8R)Iս$ѝ5,#^XOp9W=sW}6i(qdx/FkcғO/JB!O:!%[ >.1U 4̎1.vU8@s/KoòT:qP l`s=rr4tn̕}*ǯ}z5ʿeV*xRo hl!%Io$ǐT!JBOӻV૾7VvK5LE#S!Z^Aim)@Ml8-tQMW 9l5^F0>J dR]D洵w@̼IʔNI9T 7[{(2;8STij+ciwN'*o7fyqPov)=D߬7i+Jx?PR ]-K C[}|x&򣐙K!KT'A&{R[Ey]ҁ &ĔLsk[R^ >ߎߊvgmonAJ[|Sm^ɪN6hևne-O#*B;n5`Y-#v}~^5Vy>%ӫ]@mm+=ǫ78 qHĨme6N"v=%nC?ȦQ=G;>Q*9 ;S(R᣹#ԧ]2'Ui&}me)$ +۟_<Z+:0l\ g3{N&|o@jh}?%PdkXJ҂#>ՇQl5 @r]cf}j#q t7PITj;?nEZbLǥTZ3wPxGwKS_奧|6.4F8\vΪ٬LFG7l8"&[UYgX__~~cnRh<KM}_5m-G+ql=THYC~[CCNHM$LpKZSAR ̖Վ}2 K]c zj>ۓ. ٳ$is<VvuJ`v}/v\ե,_LlRUhRJJN{{Wu4\0F>+u]ktkAWRG!$j|Q ej jZ&o ķņ%еKH9;[ n[{If>S=%%qwvO}/Om%p $NgV>!uͰzG#8-N;R&'3;*:^<a}"uD]^|cXGBa63Z 0Sb&IZ-v@PѶZe_utʱa Y(>aBk16KY^S O ܟ^і^imĒTӜc#NZM%cʍ-/pS`nڷVmxVd sv qs]ثv+#q8,;w6 ԏ=o,*zI&V,M~ί>±hOs- SqRp}YԟNܟ3K>_/?^usRLלeTnWA_෇m%|G=$ qb$bGuU8""""""""""""""""""""""""""E{J!z~YEx^8 9>‡R =׮`̛wIRgQ·( {$VO:ک<SAf{7=%~^+Pm]A]e-9ڐT5iY$|$=$dw6Ɔ7FmB|E.K 7FԝGp6%.)I h ڷQtTDt-?6cGn=s[$1q @׏i 14f5e5Dt)J}Ե#EgKN HK?K\r^\~>8P .mZ#\KId'ɭYIU0==zSGu&5g%zR;;Rqjz*USCFGKj>>0T%A;H AHc H\^ t*C㞯 ̐<&TJw+98ώ+TYhP|V%G']W/7NĖާHb> iz877j/'Fw)񑍉nbS~ 6G՞2+ғʘU.ua4u4AX"g(=8IղlF\)RBU$qJ3l% RQF#`*'-!K(X'ȩ\J{ne28潙Ge"+!IH|sbpaMji u:~PB7DY 2H9Qn LSCG* &@r~IP7e! P͋%?1w! =8;윙BX8Vne GA?OA!f}.IW) *XH^~Ցi{aoR_+:k{]omoaHin ,0? #DΞmSC.ԁR9ߵ>i#iqYTye$Y415ۅ ju/-n|}^ˁtkvWN=3=!}8-u }8T?Ak% ;<㩺Wjg&Isط;nH8T5jH>ug'?׀b̐8 ө) dƈOpGcIR !r0 g`0%ci2iXNOnw'{-󞄠wQ,XR-c z(/恌ߕ:IJm_ԟjylm [LYqU^픵 MlSq6'mnwU5F]+ Ӟ J4ƚvkҹ[]N]ӕsu akF^`n% :vsIki_כl$f%J@1G3~ x/O]Au4uL ndsΐ@3wM:_HGP-vBhA0$;.[͟* ?㊩uM[(+"K@b>p>|#˯2جdֽyF2{N ۨySw3$6VxK]X\TZYܭw}H6  PJ w/OO}_+8?P6+˷JMqU6_N#ȸ#P׏o{SuϬ=;cYoX?M8.eEiYJ=?z^!Y^n"G^j.j -dxe[cjR/V-ؼ{}.9H8VgEQsd¥=k^n}DKs`FsW?|٣d9M@9 aKZ\pݿHzһj=0ۖ׋fT5iI*O=-{#%4_%%W!RE^ctb>UqQe+QQ ڵ}ɡ5<pO֍1U>ɋfHڂJ=mvzw2 O Uuu0:O4XR\6 B2}aH/aGR-G~w߿uIA|ո  '\fJYPZV-N5!{K_5D[ݸHOr>X6z= vH\n0ҳ̝iT%ER[e.d{R0Gd&hsN5͊V RJ{'<}ܚ/6q91Kė+kAĮmA]<8oCl3ƠKAPHQP*V>$UP)ޢA4rN*j=g?N?%d6U(|BXB j'dQI5&nT.2RA*rA Flب?!I%#i<[JD1\2?sT{S6P!@534A}Qql \2G&tz&JI H# JuGIOi4Ӹ8n;R2v0 mGIdV9 oIm 2RIT~j†&K;`s8oE֘/`ʚ4ȇ>8ylpR XzU"͉iN@ 쫶˸߄Bvh]E}B n'##<4cVA-HVu=15 DEb}IP^;W@tn66FdA.1eso!L8"WAQR- 7XFYw.3i?p*^Ӷ7:d+bCkm;*bS[ %R{j[E$?z^E&?;o1ѝEF2$@>kXycFXSVmwFGQTOvR]%:>x'*^x g?U_QTyyh8Zzs9njZe>U֚L?*#PZ*3qNB5NwHW`d2*{dU9QtT/T k2=-Ϫ16wCQږejbkI'=V5ڜ6 (ڇ>tWyMv/ٓOR˵KKcܭs-J 73#w+,ykqG$v/J^wZĚ(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B+'"B(B+ !B+={! CXd[EdIN(+ÞԤGq@^8/~P5ӱ/}wrZ-J)tJk=SR׺Y%?PRS`h{7~STŶƝתrKoM93 Zڒ{?}h enwGKhh*nAN"aflZbT{Pز ˷lL"yjA |%Ii]cN-o'1$C~kΠ٪[iv=_5rO1Ln'>3/@s*Hcf>p}E\iFܙ|R?I#KR}NX6J‚ؐ)W-=ʉ,; 8lvj3I5[Ȳ!JzشQ ȉt1Bƺi vB̖PAn8JT䣁QòUMPGsҷ{rMƅo~{\PIB[O NHRԄ$DN~Z6Q1$n;-HYB=~c׹/1ar7HDB.=ٯvrRêry{ZCq2omkd`g~K _N9{o-Ҧ%#%jSäO9\A;q̉uoHuo:kuhF檚&yW8+EdE]ouzq#XۂN3TS_mh;S1*m~u#~on9A='t5ˆ3ޙ@^Uy0:9D ͦsې -vs>8 8VZ r`f.QS&h0pױ>5Ĵ8麖Y!ZFǂ2#iՂS/ٖd T9_⪗ fu=CK^݈#)jk!eב'v<S8[K4\m ֹ0Xe$NHZFXf8{R)[G${crSIKv) pzP黍%jm!(88g~!K$mv p|c9ƙ<OUqcc4F;kg|/PJ ݰ-$'H-K3M$"A.9!G*R^ysʣ+LänSa+R>x~gW*5IiU\D{! {bCVb㖧棟-'<όV\1?j>؎WQh-7n?lGO:0Hqy$I8 9⾔ٮ6hoҰ 6q)xvWYMW5V7P4)A[[h1eqR۲q[RҞyoYn'Nb*ZoCZG1uDu>lxi8g8n>ITRWa$aT%6$פ&2U9M-S9lJ;o3;(E@Lp?$RUsC6wUل+}aP9OT$iHPUѷRo4(XBtufIv'4ɵ5J*{oD~u4"זRo+a%N,EbG[?-p_1-]EsM0K$s?Ukz!~Iq#iOzx8eĺ2-]3/ W)B5/—2}5.;Tܣ!Am1` D[Eԡ۞EVGG+#\J[ L@=rӼ2*F@v(QZnpS]W=atlisx) 4`ISl7r։it m4w^!%\iaaNr}Y_%5EqtO>w ~;aŰuYOڣe4Đ?H'`0YG׍Cd!*HV@ z Z%> :`eGOt,] BW< V/ªխ{Ow+?=kEw98qpX^5֦jk%%'>¾,YIN0֌/]+N\%R(ExPPPPVEPQ(E`$W".BV SJ7=o_~u5ؚm" m :GJ@Iʉ5į]C5/&ǀ4s\rH}}e%;>_;nsQTzK ʸI IpUڜoU9]`y KHZ)nզ8:Ek_NzUk*Rpl {jW>IGC`s4;@ cGn:sրm&L{xQm$gWԝ3_#펦?%wpӃc =E{R5n1|?/:*{0JR=|𪗦F5.=7 :Z]"8۹.!湑!!!vpiUk`igP7qt*?zմ6J6k#y??Z7hY{W qKeRFA|w}?.J([+$zZ08e@^gN7-AK{i d?. #5T! Q)J@d҃$'kSj 2ScxI<']9'˲.PQׂҐaB)'ۃR?`b0@ 0v?e_@9c|&SVTBG2|T/ifD7@ (h' Y! =-v=\G>[ N#s^ \9?<^RF!`p6[MyqD0v8 iӖ?O;GI+pWe%ȚR$e i^u9I4pzNI%Q!A'jЕ% HRHNA8}+-;r;'kag P9MSc)BDd5%6F+u 'iwz(<_}$팑~śҘieRiR;U3g:7TZ)ȐO`X|Dtm<7Kڛ8SFbδf[ ;jy]_d2RQw .K(bMӭ̘(1V5UQZUk^Djd77e_}+{&yV؊QB|w*Ξ!}5va1KIVSk~S(ݝm)@灊|;H4IY7Ӌza>YGG>iÅi7Np襚i Uz ikۧU/u%VBsU.Julv Wt;p It`(-t&#RLDzHVR+X*V?j#aU⋦n5+~ۢX,a[givjC2YwT*ާ~B|Ȃs U= ٩|{u>!հhղYoD?H-jRQ yFʉ=ϗDe^ (W`qUЖz j]qH齥JS G8&3_,9Y;uK ~+-?5v33Cq )|DlxkIy&V>TO9K+(/,nrSH sQf &'9XȳB#^mQ@/+8?R!TqU81JHY(ԘUJ\l QfaU)mU4MDIԏ?5bûUtgPo'wly5I/ 2 Jti[v*ߴ֌ij9%FdBs[sVye[))"\%:F7/Dcf EQ[8]-=hڂ ҥƻ}s5s:R''~Yj{Fr܈iSչK}pKlM=9d͛9<*EpLmRp_PѧYlge]ѯF*jh"#r 7,g22z9<+}+4̃ ݏ:^۲R~U`)_<<:O/Yu5L8W?3UXͼ>J]Q +ހR(׀ _!|_񊳩q"\[ iTPPPPPPPPPPPPPPPPPPW!n|P͜nWd"-B+8ЊPH$f3hq SM '(!5$R$gy^[޲VĢCF lcZ^[dH[ږi r$OmPךf?5f\6 hGfIT~aUkUic@.={ivK1{e },Jc y N_@0(e kCKm`x{ON,`(5^'VJ`$<&dc%U ,/|}HL}Ο>'Ez*jV*I ~v%\f:6hG9 g'guǨ&=1/ ww_JMJ7[d7uvjEu.չ8;8#ޥ!-x% =1G|Z=ǿTsJs<Պ(&\K1zk "MoI`%dq{D|s'b@,qeԔ jʓlx840I)ɉNy;u'N}#,E(9KG=ojʉ@cD\)^[R]v[[SR5!Ϸɷz9B uRJ'~xJY,cS&[73 rӇ7ou2/.&KY8 *SajUX1P;p)QfIԎ!rTFF*lJ6KAus̒FM;# gv:NZS&B]&Z描c HV-I|^=857Bv%5qMKhEH)7+ 9>MkSvwpl$훌mNgknXnU)4їٶ-Go~rae i\)PC8=QEPJHÂ{UD-?oG$caMlCe88Gsn'`PKT*\mi;9 hR[Xpy[`TzVuMfS$8nQsFR@hJ =#j3})՚RW'!Jl+oW|*K:g .ޮ[f@wωֻۣ[gܯџ{rl p n:h4rP;Sp8#u) gC30H\uj92TY~);{USՒ>=eдS#.Κڊ5c[-IAv{)a-0xHG*Z:*JߺGΫ؉k񆁨o=ib^䧣!ϓV0w3>TMӷ[$ae^)w?CMIYn*r?\tzu9X8Ll97.6 g[o-:F;62ӒN#=]oi1H47gKAFI''Iu'BYj4rO|񁀞uU|W⋔-HKMX@dssZ>q[Iq:\rs\xLU6 흶x uҺݥŔ}1I#(W)Q\հUk=Api.ÙI 8#!LtNSUQ>"?G9 Ca'̳ɤ5Qq7e&ZG {gm7JZ78*+? םh8Fy'cRTU()lokCsYqG~4K Cn >?-+Sʔ8>w3B݂7/K!_eP*?ly:;cmUk'N>I=ꗯ2FTSFGMrh%aCVy"$H߄)$:aA?cA~;&aox@ SPOhc.['?a j$;Z/tu:V_恲}/(A9'@Z飩ioMs#pmwnZ+v|T-\\;WfgXh]%z->ҊIC|3aWFpp6ԯzih . н7yjz8Zl3]y~2::3Q`۟=Om/`iؕ7DZlLvt$ pWM֒RT51omKil\5ۗ* oPGRBpƅWQ;HL^TlޭVU[AgYaU1EJ9 =s&[Slح8EכoOv>Ս籨ޔ\[JFqRp/=GGbv3J-@6 cNHEzK4K;ry5)(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B+-;ePc^(ExvB+2RB+=8Wp=e[9ӓ9J[eKW< ͔+; r#lYA4D.ˆeQVy=IO;/YJh-l ȴ~Uӽ7;mݽGp PZBNb*ӟn1K-hNZ2媶Z2hl~Ǖ齬_5dw%j,+2jGnx%Җ9*a.pj6=13[S[Q ҽwY/N %.p 8~u)_XI<%w em}A勄 v~mW|U2)cVF%3`O:_l(ǎ ttҙ;OkG`p2>Z'= 7+#SWĂN&Ci? n)[8nΔ)#bx\ t]TB [sXfxSM+<^3YNMd')sQ<}o!'#?̯u=L+:8JӺyE 9qCjXY{2W\:;,Gfn{]J!!!\/R!u:v?oOy{2p;{ u][zv+"n$ܫC5è+o7/<ܟeV&f?Z\ܛȐ-y5depc4C{?%}MCH:^\N DRBkL#+<;a3=0098u$K5nW$sjv_W55LNmnM'f%-R0E=n:Pdc2r;$ZFd;'J n' 9:┟dѕ pBS)#ebcNl<)+ je+A :FoJKj2v8gސ'm=uc|jIݛEj[uJ߯Vվ@ cԅϐMXWPHc#lA=}MUQ2A2>Tkkg7X8 9:S驷6S줥j?R$w}KkNz27pQs2>D*W.|+OuNP-fof&o9 Hrr*nz T&bF<ߘ0oIQ2dդK#JGuXkud߭3h*k|F+RTӹ+8=OjYY}j(ipp~6*nmalP.=pj>Ra:bJ V߸XFmf倻JtȾgPʕХיl-i Q٩kL4hsr ߝgN)p [xZk]3ӥRRE<Ԁ%x@R=pl䴇}8f@6k:F6uQҢ[|Q A3Qmhl%+kZ-O?GC@#yHJ8?r뫌٦ptAfKZdՀ?c^p%)Isn18y8?UV!{ݥ%HW^`٠7 UXKV: C+H'Ry7 )[7wxT~Im\aqw*֚լ"ڢ1UD%Kzvtc}64`qIsۤ-ըvPsyC`d]Ym -`h_`_UHwQ?}KdUto>qLNNw(GWGQ3OhW(% uWA[M]EFlvSFC yPWBw76 u(5Hx =06Ɲʋ랈_B%/ӱێ|lh}I՚&ckzH xZBvBSdVWz]&%L<nva. #YD"hn7 vQ=gdu1K dP?zK"  :.sjܮ|̱T2!+p'[PS].2(u:6?YP-0pꛊ]!~V<1HCeG}\vj&ŸfbHd_UE,R0.W/[:P|=3YJ ֽ^\$.?|IދuN6ͫ1'%[TT@躶TE$[9ʀE$cpS-e1z-Kp ijpexO#/3m CeZ_z/vVgBZ˫Qtޞ&āVrpIΗHQ=VS sacm+z?Օ_">Cxi?j I35G>9Lelw n+ud|U;pAL\! D} gOV ={ThpWڷFɥX[A);x^XSP$GYOW.ª%BIQE*z7/Elt^GJ5TtWu {r4/ E y 7dFH]9A񿦬U)vHi)wSCp|_.3)mI9|+7.Y:R:I18]Wh>LqUPhKW Bq(++^-ӋuCr^x,tCk앸 kz$5Ffqp} =9k1cb._<چ0| v48ʈ뛬Qť^ڹsl6̼OҡIuX]'X[֫U>vk\f\#۟޹FZ頪26=2]5*v m8x+T,2 MsW2u=R<9W IGG)%gpq؊vӱL ,ce.=Wp{$+V=?JVuEU۞+> #sco4WJu2Z3_Qu_IZzNô"\/#tw+^) "/Etm+`n;=lsj&3tWX=>!c'9)+#?jX [B\T =Hu9aL "?rGBu,(ޣvO`;9M QÇ':ihc!qgHE䤥'Z >Gʥݸgw}*c 89M旌OtݨY~jmNL Wi<?+oϑp۔cGb?pAXnsxme %%Gw-<НG_*|{3S>/WUB$?  v{\5۠WrE6 )j< g&7,tͽ8:ofw'Qsis cQ &l=a֞jԗ9Ix{WWʲ|}lNͪ>5sbhu$%C>Ϛw3{ >V/k@=rAp :'l/.)$@wLwyG aK2Tvߊ %#a JB?Qo=lou'jNpq^;'f)6b*PfɘJW߃T$d@+80x߰܍sWCǺ]vWTꦝ#B\wKX꣧WA95r䩯XԄ>'a;FIF &FjBНܜg|R@OLM5m[?ljE,yMa#WV p*qS6*5phƭ9I7>ʷSEEK/ޛ $!~3%Ct֕+-=Jakt%Gh'JLم5NCK'ok . w; &ZT3Hm IAU BԴGڂ]J8ɧV2ƻS=Or~tRby jzKxZmYԚe>oc!$yjY\[! )]1ipPa*OR68x&ZAzX; w?ApR#G!Q{KV3OS5`rpH n.ԴHijHVhqw_ItBҕ>RQ;Tw8zmOS e?x~=X{s -5$}[i8\+պVxjguM$J64P9/v4c䒷Myn9{{ w%t>:lkJEz4jSݏ2rx^_:ƺ7L$c0 ӝkOizf{*՞>t]3\L1miiVG՛<lD&Pg a'8탐=j[mL)b<8ퟪ,S4{mM;VT3$rHL湧z'3V[tK4vL2y 3Btm=(&%^3V$IhOqQCW{ P“^e1 ,)c{KX)}{2 tZA>ls33-(ziwp8R둹–tT-?ui]]JtkoX "bOi˖|qwIM=|淧C-μ빼$vw+uTP$z.{Uՙ bn-AYQh([$U#z[]O-9f# zI|a]b%uoֱo2%p8?qR7k#m5G?S{H_Nv$g^{?q\E+Ӟ@YmW3Dqp.'ls3gd0e2HD 9Q]-a!m,~LD^biشK6@ROX_p=}sWMĔ!ӜGޡTF!%ԏKSEeO.:9<8Oi-VM/j} >~ߚ)`72{}OeETVT}̳'=Qq$8_7Z#H t{~#pʈZɲd:"w!\;[+'em8l} ݩ^~j^fRw~ *PF*Wfkaoe&q73\s>)1[ze AJJul^; ^VԒGx.~*R0htG_Áva TTpcCZpI3wH-9pB.AӲtBa ex_\JXg//!ёv3UYմl;<|/wNviˢޕcWy?KavxEؖMcRHk"Î8ԯ}Wyf uMQmjM%\.>.+o^fU8w>E]uG2F!}R2++R1жR֎Åb堕%*|$Xfs@5BԦl9j~R#BNrfԴ xR9s&JjUݟKugO~}W٣3vdž\lFO;|ٲ'vT\~BTD!McC0[[-Di\=JQ4EEEEEEEEEEEEz ^!!!!"'(Ez[PrWE(IB)VW![/SyY JI8N#nW @e`E9Շna;UHINyN`0*Vqdȇd9- *,@N)0Qǧu+ŮHm )JOaѩ%}# V!IL`J,Z̹Vnmԥ*VVU=) iS(J*mgǵBK0Qa:FiJ8R}霯kN-NTpHe79FF;hb;6IYSIju }+?SV Rrm3ݜ/ 92a{.܊ h֜(i3akV}Ū]M9mp!۴2_2044{zlێI_ϊޡu[uD{+Qhzh $k]tq&*qLIBWwoV{qڂ-gyTP>`~ӿ̖S#-N8?9$k|vbĊ8% ʪfq|.'v-#cImޠʒMC`k/<jFn VIy(p'`bi9 XIM8TSɫ*!i';RH[o"\v {U"kԍrXxdO^̔$rvaӃ4=n*r29X\Fv n>2>S g QtF2i j7 a=qJo*S 35]%mJ}I9ZR9*WDŸ{;ڑɍCuie@I n2NO ʿvm i<827rn[F V BM$ܧRy?X:"0$Y#HDGU/v+siriH*؀w(휜U˦-qUeT2IO,i d?dF]kKNZpD~󷲯+3ʋfqzm)(pOA`a8}[Y!c]7ŒTߦ][ aY&gPہVޝFe RA%IRFx48rjII9ȥIf?vWW =8\22ʊJN* uu l).i!G]tgRWF$܂27 ʺkY+y9 qGǞsUi*fs$I-렉K48v08yQpO/Etvj&$%W!%q9Ú=44s8Lf m! Y.L.p."`'s,.f»[y+m/Y|.A&Z񇜂d?C}owwӮ/DHRNc=Ȯ_,vvDe#p㆏EJ9ҿ~8FtEt_@W eĴ`)kRc"wJRq%.gC:שt6yh'xh?aW:WCIW lgr֌gnތ2dTQA=WW▜mѐ0V`t<.x0vK,Z˅ V2 ϵDVBFw鷜ڙ8O9 % sKy%%%$8^RWg8^,$`Jn {RS`)\TS'MM28H?U>c[P=2{V.`{Ѽ/ 'v+ rݖ:-$v$%4e$ӰyS0y䶧8K@TT .'<0d$v[M?xkrB$m %Pς9 owEV&H38f"o!Dc:VH6M@KHdxi n.,,([ܢ3@PV ג|$잡^np lHPO)(r@89敆h|Q?$Gsswx$qcFVX+@K qR;.6^ѱa[xXDr6Kw%[`LvyNgQYANX{vq.eަuL6pRSspT9kO'Ty9Z픀rn]ɈJs s[m֝AC'_[;T6!ußKm:T7m}zEhΔ)iϜ@15e\wam'bGw HUOzJCjkN?`WjjiuT>+sҒԷ>p8NzJ~lSuO 2@ggm՗Ŋ-_D{>{dWR\ZZ_MtL89p lv3d<ݮ*321zݧh:ƿϋէO]=U~۩/m- Ǎ>4wӺ3TѻssNCP&|av~2.EJee6!NNHɥ[GY\wyj+LCL0^cvr80N'mQAHȠcv-ƜQv6{..t[Mhh䲨p. %8\n- O$cڪG1s+ i_R;~yKkJ޳<'lgbK1"߹ՏesU$|ikrSZ˜mnd)mؘ\GRNBe'`4lɚ_h<OsQA"+t΂jؐsLPP6^P̓s tT~[])ˍ[+pF+mHZSƒrs{QktcYޑpm~3);uW*ky*ELmߡJQQj!I@z[v! J)JRLW9A_,;.]׭4N;ubnOtuY-3EUHav_?,u7#tvUhQ>ΒFBjvጅ]-ETڙ2Lz?1޶O@.GmҖdZFe% ӽ%7t[xXOsZ6\̿sW~ [ִAoHv?u LV}kj7\*jO"v#ޤj2ԖcXڬ퀒)Jj@NŠ$# ;Ie: O;li.!)5w=1=Coj>J:s-XOߦg]YZ8=U+ܫq<µ[zv(iMZ:GS1} ElHkHQ:\+/ZLl.qK67+5OJtҖ6IHSVr*>lqcwWg[-1{W.z !Z'LTE$)v~*AਨI!s%;QWbmzCm]纰Z7.EByIR>v[ {@~1lؼ $2%H/tr}AHPmK~9?_F<6뇤c~7}ietCT/ګS5}e1鳞QRs}-)!S _Tumڭյ.soT""""""""""""""""""""i^B+""`'<҄e A1^'a Ķ?޽ 8 _ 'jIxveIx2% @W4Vmh!*p|dCȰV𔀡J)̌hfp!*B3K 2hzwn *# Π! F7=!{Kpd`RQ8+6c{$ܬG+< Iې|?xS֗U`iT[XmJ&~RćeJh*E챷O >U6FSiJӼzBcq\WХw5KpUƏ]/OeڟK<,/<1ar1=&U>W} miM*C`u^A )UBPx= L:F}J.܇rU_z0 ܇l%Iun!I!b-&ǓYGeמ!J]`6 {fܯac#*LBqnQNjP1'%(zČ' g ;{jVeF9K80SYJ[2KziaKGBPrV[;vMD]כ -|u0Sּy28B~ QJ)?]4Oł ^} .$Spv8 g7+Cj3Yn-%)OxW*BNF3XeQe" 0s!NRfR1,F]ڔm6 򝇓qHPsKL% J$7pڈ( ( -KT#wZך[k˦zwdJSgu9A#>Ijvᕿlu]I[[\%\L1N}Min8 }WR.֨iC(F! iJ[G:+WXo.׶4nˈ=(573Ued9!5@ nW?Wn.qD\A v}xF::B5vqm.9qӾr轳9 ΧH'ӤouGW2gm4Ns]`Hw_YkNX i b2ķأFw}'KTKF[lL ,sIo$ulky}L1m"Aj~WArӺeAiĐRr;Q<5k@m.8>NH]2GoLnGG?:U"A kuGKzNJ[ @.HI8*do H F0rwQ> gڐ*>j3JH+qj NY !L{iJj8VN'pFqSec550y}[@eh8ۙ-X#Z.PԵ$mWŸplđ{g/SOL h˧t5z[%iY%&tC湲Ǫ26 U9 sgrn:[ pLZvv=G#odߧ'^3ԓ1e~JRHbU*2rRTO\GOd K77)hxN)8a\#ϥrȘE *9|ڬ=156Ѵjst*Tw'55Q[7^/͐tR5ڷ RK$~O*kBNYКP3Tj5A]ütGt|+Ԑ[֐x+rj(ꩤ.{H>u%t# ̹_Å ~Eޭ6MWz[a>G.e40w %#<% @h؉%@ZxܜѮcpUԖ]5R:nRԻnU9e|Zez>v~%BNm8*GsTջk Y"alH=u'CQW4|.\ެKZeЭZ%'ze5"5bO;f]ڪiw%z_螪0t}KS\eiy~9Z2NܮO?ay0A~3^ϑ|.{NAΓΈ?Uqj!*F'jO*Q^Z\3讝&}M9Sy[1ǹ?c m.co̮)>puv< 6"iirpAA >+CWMR'N{6>lKVvI^I9!w8P^> s=Z4E~Mi2/sXŸ i%#vgެZ1F3N33ʛNꙶEq$DVoaWqEW14 _NÛp]JNTrTk}p3Yܖs._7rQ}̡א}$y@V.In[v_I5$uY*RI$Ƶ|ᚢIdܬM*2vX5H@I SWdª-'!&4EEEEEEEEEEEEEEEEEEEE(^i(E`RiEfJۑ^7=зzXɟIRU$!x\gb%^ P>k)6́YS!sM)T(ʔF }Xd2@Hds%JBH9 ,&C(+3N;-Bʒ~Ԭ-)H.JVcsHմW8Wohyyn Wo'hH)O׌fh-S+OJ|%Ui}dYOJZ Zj[6-q5%GGE=`0ğYy;;[; ڐ]Wt55.*J[iN )J<%%@~CN^x )Z[#?u&3WVv 2mlMryW z^ 6kv T5-TTv5nusYa'% 8T)]!$";'dIq喝{ft%Vʲʃu1WJ҅`ҠA=KPq?F[$1vL,Dzo6Ճe -Td9$J}E,М'ȦkIIXBT)μNTO7IdifIJrRNiN$n zgI/)D@0B|l6J}FNdsϚL0+00Lzed 7O#a*N,, }NQ7 x T{ӿܠ2U s i 4ҖJ+]WV-g%[jJR*fq0 uQgq$皨!iXu5 ],NJ0?]ShmqH!;>=\4qV=|3J{Q}F=.zJO8;~gHDY!indgw6m:h#dw^>2"6'dple@qD+@ =84dN\K >l+_RFN<`{&ôM"K5gQߵx[H"˩ue3!XY-9k{M#l舑sE@ .AEGOJט^׺6i#`Q֍Eŗliպ<8[Ǩzek5,Ŭqc18q-mkWܙkSbRAGZZIKp ziTgQN |Dr ݵ> C"6 hxJ}vhtކM Y٭2cDsqza04F+$vp䭄*4/-(C#?O?t4PZ` < sR<+kTV<+Za -- jjI [d.+.*6I=ʌmK<-CnכmLqSōW@i\4򌆥:?y?\?97}=# ct9(GQuur.EeGi爞'u @08 {:fNIKaHOZkuHӃHZa䳸`+&WǐOQ[)9{“]K.%ŧu|TsS%5tg<+9 -`]utB{r1];_}%U8eSò3SLhg./}R]u QRֳ1 ` e'MNx?1dIRYp';{{уsKFp$GR5 [ ;$tEEEEEEEEEEEEEEEEEEEEd2vB+Ef,  ${m;dL bqNqȬq/RdՎa {7d֥iejVR=4%.gvXC*3&Za#XaYM`J3RVzu=8V3ګty+q#)+0V&/`<9'ϽH (^OvM<9YDH@I27+AO?z0 J[9 Q^: xN[qŴ'p>ưاt@%ksAR<nc9V,Hx,8j*XVt+ Y$$)W-!bfI>x dvvQd֠@ ǚZNK>2JT5`;)N[;/#ڼ)xC΀nPC#Y;="Ck-&O#N;p4@i!69WJ*WN;o\Q!M.m)5Mmq.B?j&Q GSM𒧠35G=#Rtc+c[8V6 ni%+JoL:j6}u=P'n1+|fr?N >\MaՍp v${atuUM>R4GJ|;*#yܻuRlOhw9ޝ՝:`] mؕ?JuJ+/Vu {ޡeiJ.0.|$޵]2+DQsxmUd᜗8lo b%L:C?E ҽ4Y"l̽XW=0{r{>O_zX}^4cIUyO{G$ޜ8=SFW1zZmJ8R.damܯ՟ejꎙ{o~\H˵1$v8s69==w=A$ v7'GSdV6 +L\4_k dv7H^NFKsGtCp^ٚ\7 pFlo Ul١C' HJ}( V eMDpF82r֍GNNc }NGp񨓩9?@Y/miP7i[J^s5\z- OAvM%C;?ǖ`<KSO,&y ?O_O)?8n:!mBmE|oڂm>bQXQAOem8eg:A8V+uƟ˝  s@C'_"z=vWViA<:>Y,6D٣^᧖~n~JnIml2{A-%y`vim՞ƫ7]KMHgvVEsGm}4%?Bq \H E зAJޠ*)ڭ++Mh֭8a=Ru'͢ʮSi ʉʛPP}VĪ.v5v_Jkn\.s G=᝾ C5JK̮k],8mhBNJ߽m<nS#̜H b`Ihu B\mXVGI בM-0cNzۃAr6M&/94vcqUO-,:i% %tۨ@nR짺iԗSj@p/s$T$.VJJah}Dž}Vd̜n+o#*xXIdn-2QR kr^sSفpKژSw4ԓ$D8. +4kOi]ՅRvAN&ӲDHZO|TtYQ]Q,~Ԉp•*އ}B1t4/oc8SVN>ӵJ_)NUzy.l :P.dpRq;c|483,ڣF5Zd%)A$'ϵ)JlVPƗԵ`}ɧ OtePՒ:O~A`IBԏ>{ kSSCyU+P6 XˏKm; ( p䕳dmY _l0IRTR #vU;%8HV[{m k!It.jIYl0\kL4- k*[OLh*9345tU>苞E׮"m™OzxӦbu Ϡ47~WT;NhKP5+gwB];&_hM~Jb<;T:ڛ-t˟Sqﺼt͡:*ΟIˤ4P )J8'qc-;?v[4bi+K!?ڇt=u2#cvcym+4+m*u4&f*ݨ5]x&m閅Z--^jQ8$~s-/PuOWϐ:MPdۜ٭kܝUxzNJq㷹mZ3&ҽ͇k^|-夬6R9ku^kw%?{I2i6~\uPu,/d84H؆~Hx\} m_Bkvۭj^ Q)a%E+tRxQ$@'qO~c\*|n ck\N?#kn54̤/d Ć2s0w IY&7mѨ`\SatN}iZF!?cN)T |zZYP-x[mȲ[MOC}-؏gqrVItª(wGPo)n)k C@O*9_QU'NG5c;ˏʴeu:[KZܺʞ) k*|ڐ\; H|N1u=4XI m<`}MuOmc.tZ7KSJJ7qܭ"=|- 4W T*5<ʿAҒ8M~%IQ'kanu3coyxSrL"c*m/*yx GP XdzhFPM4ꞳYMMٙDuZa>T*[8UҍՑ\^#[$p\c ms^ UQM(Y4J2;b:{p0qVsc?I*ڌ0Ф+[;>ޟ*7 HF;smyw'=VJyf~ t5q$,='Wps#q'Q4Ǐu؈Mѧgt Z_c>v?f [=[pߐh k])'f5MQMzk'j Kc `;d"qgSV^ M[@kAM&mks=[l6IRqwՔzy(݌zInS)#ۄRR=`;75)-D% ~)Hv hz*I4i M! j(' d̨)ϵ(4wXqڅ,QBBBBBBBBBBBYvB+!^d JX  P@zP 1Y`H3cԸ6T;JhJZlI'+S %X8HzvbF7e$zT%(.-e 8dyK.i.$`rn2.j1J[HemI v<ԛYez }T-q$E bP-B6IIBNX))JN{╆BӖzN㏨%H^T\R¨nYQ #byI] 25 aM&}R/ $Scj={J-%z9$4krT=h;\.J6*j3ߔ70&tߊ4nR*qan@1QR`גMYP )E1I 8 +}5<֖ Y|Y!GjQ8RW8]YA=!A%)Ym #%9kr kw+,IAΥ+${{R0ytmja%cWdj:x=y˳1!ZJ"R{sޤc~i|((*Y*מryV&F2=G,Q㊭ہ#l*Pi<~WnU…YKÜ߃]J;?K/SBHT03]ԽѰ 7PZˁs,D8`apsp4Xmpp8x6$|.u; J*W:ix[Ņ7Tw#izf^:VyXJ7g&Ɣgr98hu^!os0pr$Sc{ PTJ{^q9Bk0EN<+9dSiivWxhhٴIz5~F\Zo0 B Kmܵ+?(::{GNRƵoZumOݙ#òK@0Uj%Z75}Tr.3-ňόOjv5 ]/nq>\ϑSa%D쌯K}l$. n s-K2Jtے~X)o:ZGCl( ƊKHPN<“k7;yvNZe~aQp:t[mcvZ ++J{T%>2.4 .Hma'g@ʻY)CPZL=!=úܖ{X+>t֢K4^[$as-#J$涟9~:Pw?wەN3#] g*oBKרc]ޑ$܅!_RN++z^*'{C2\@՞O`ꉕfCM䰌HϷ)^ŃPE3*Xn )BԔ8ɬo-~}5%m 0 ?7ELjigkNsq'^Ytָ뮝 KӍ!С*F'4>u5N$>3KOoe_]7-g%8/=WSq_{:N!v;<3wJ~grpO&UVWUX%&*'9͕6GS9$ n{"sw qת:e{.n,G!xR5zb?kzb[C]CKp I8q9aJ%OLQ^\ƺ&45!ϰy:aQzB֮Im3lH[`JI sR~*x_uInE4`9 5 u878Y鎻IFh(\4\grF9WWq5rh)j\wjڷ4-=`aYWT}:v]+OuZ#w2K򜍀s|bQHȮaI3A;dӬ^k{Mt[#am/<xzў/^o,uvk&BA142YrlWNc{5;沛>o{ _ñaK6VL%y [?PcjC<4 Ќ:،׺PK%kDCN uWRL.,9 H9;`T]祥.]&>NOm즃T􌍂6YmqP)Zje'zq=%5c]$*+W$2Y+G!'B]M3 q[VObx.Y4`Vllh VcYP9M!IL`u+P^vy:Ze mݷ@RK->,T=u9*fMyԾVsy =cC}uƻt[ xW+2 yMՕpi !75P%S |Lwm7%n9OPd`q[\ZxHԄԯ8}79r@SԑDtbHNͧIUʹH0Ṡw+]ebTM{zqp!Kajtv[rU"JFRPjFZ>)0+S]>vb_,:=F ;{_(OMB;^kRne%6I)7)pKRl2IQ9`'3anA4S=',HHWjfW Sypv,X&^v[:U'IMe:c8Q+,2ƭG>"!Z[ɦZ-sKPdvX>Z url'\-=34ʰ3*ן>pyR WMxq}]\a9U.:+]9+':ts׸Qˣ+韅 kn_/tJi-`!pLȔ<8NI'$z:a嚶#HujczQ~(S9B~b%C3]!d7n?H۲ؔTS>i OFXu/aMq_yvJ LX[akm;=@z<,L/U-00{cJ}!jCM+XiMgq+>@д  Ғ.j"n;;RxNQ#ܦYS _E? ^PBEiqoPKdKVG"Bleu!{[Yڴq"@}irVNuŭ-Anxm 'BZ&)x%ϵ7~S? LS)$#-g(` ڰS(H$,Vf*+_la|J({pxXӌZ ouzHA.lkOj:f;5:6 [= $]lCZGSǗn`-?Խ;q 6I{ӨpY=jnjvB܏(Flq2}TSˁ?~q{Z㓄֖ϥaPז 8 Z].! qgz3]Rw3mz؇ Z8X2 x58ԷE.yP4#jHBq{╪ xp9cloG)35apI5}9NQ%4%(p@ikawi" 0 %?JGC 2O泆c#'n3v7}yэw @ꑴ-Z3*ZTRR ) sަ:~OCx)$5pUQT 淑HneP gBNnKH Xeiۄ{ֶeVGl@ ::8؀G"׶oȢʔT|eL;m $jJF UV?O,:[^2f!o(uGR19rV2la|Gߕw:ܒ3m3Ǭ=ěԭ}䬡d%%cG8'Kφ=EŎѾ!bG ~9®A^;dqIGSKHB$pY#s<8fڂѹCnz805fCC2;-2 #1G#L*)6xgkaa {T{'Tafjv9q~1)ȭ$ڂXJ JR). h:T+r6{V$[ ӥ*bRVY8j`hmFuқ?JNDAi6cʱ]̴Gc{`JI[c<9WK|/uIؗujU6DU3nm )0{jxhq:g:760wc| *LJ d25맬CGu٭'Vc YI?? mk:NWJ #(CÛG~ٯU*9ڄ ;Hϱ=+hmfW::ܹVˌّrB eYRRp;玕?OKzEokO=.|ls0[<֪ gkdk[f{ F ՝2nr.Q.fSܒf\a[r 56%֒L_ X/c<@8Fn5gOʺt ]kkmȒH>qX?|4t"F(VrTQ_7l6&S2!ksAϩd 7?tO$s[2DY. B_ v+AsQzOh[3 ik\ZN gw[#, ik0 h88!rs] h_Ҷ:v"CBS)Oq]]׷ 2FHHn_smO:ny$k$7:A#)Vr@8,j-V&ed@㱪f[ŸCI}CGUnG Yܬ򥚣3.+O?ڽ@=:;3' `t) !O }1_z"ԩ}$`Z\ָyaFVL3cFw{״'VkjGPBKCͯH[Ns!JrSnY\5E1<۳HCHo{i;nYk8i\Sz%xWjdⰱ5H7i J@L07V2&pһ_B*Q9=ʙio*N m1y)6hLȵ銆^p?6_}Uv+v$9T\%%ߥxز9W*zaV~Tʩ5n5 Ҡ>*{H=ԲϤc))px*tM'8)S~\v7x߽w!5ek\ |GgQ[LK8*bƞ.GMòwO78Rr\]PW!f^M Ե\oʂRu[O :e- f۲6e,fyc x<|8n@M3p_QZia?% UYm7Kj 񣦴r[]3{A淿Hx?]pǤ4X\2o^LitvOD|w\O4#'a>&w(f?jNRP4GN /VܞMS *ZwrǨBL`6O*ǞY)A% Rex@ 4R2Bp}' 79X9UX(kIY+md$)Ͽj6ǟXm;}ڌ;sO H9+nZz n9O˚p԰NoI%S57uv1JHSCDPO`4xVI^8;^텅fV".d"Re22V-'vĚ 0:(Y dF6mPwmW'/+ ܥTX[Q'$j$`y4e pܔ;+Jݒ %9#8)cZJx.K¢2Ya}R쒎7hfW)A"'j+$,n沈NF0$?@~[5gђp􃏽{3ZGΌQ$%E$pi2#dRF⟨3y!&SPjQWNG&k6.6X3d3-YPQې )?c_-׍؃௲4 q?DoN |e_V!! ԙRT!*'9u5d_M[14-fe{ ۍ6{o@ʔ"'A8ݮ izVvގ8i+@({߯51+ThnK8NUڳt@9Iil|W#8b2v]%$HmJyBֳ9VzRxf$ wiҟ0)ՒHT`5dw9)S iXJ8ˊZO$WRyҙ-<28%r\c$ Sm$3‘iYm)Ur{Y20Cѳo\\"j~i0ClԔ\ (Yp79,h{\Z Mq)I9)oQ#Z-VkէG+.NHr#ҏLT䣾x&"|-q lFN a:, ~d[sm)49VyXFFNއvHPI84Ȝ)Dw܈O*BƱsC2*ߑY'.7ՂTuhB$nؔ8H$M[ ,%9Ü9O$\#M'^1RP1v5[yX v ˿g#MCO֥qBG'8AASMmGGIU %XFZ.8~-I#ec)JVޤxrT fԷKdp Y 2,%=U#u7Se3O6{֧r~㺿UzLjfAvמT{ujp_ӗ q <4Ͽ|'ҶJ*Q_ BzTf9 >~t1hvn#r'!6\%red>ʶnK׎^} AsX~v5FqA_ZAt $I9hgqaqϾU-5㡴JYiպO:iL+Lv -'ގ,6ql :Zܖ\O_}{UEl:Cƍoe.^q]˧W[z3_LW?jrJvsy୪ښޞߙkWkFK JLZuHF2v<ӾHJ55]M2eq_ZJTr~CxV&Ɏ6TkeĒўmuu6e9ډϨN*ѿ:ksz5uK6˃h؎HHr*RվW7]:AHѹdG9{y*Ԟ0WtS[>ep&8 ;'9hWX|֜:>ը M9BB} k=>"Kwl44uEk0$dF=Hn4:tj'??3F%XO.S5w=asQ*q)wIBG['ltǪW入>Bv01fzwId4548 'ܟsMiujێ[kNtqx. <6^Ldi)Xҭ[tD3oT.Jq_6Jo=+u(L M%6Jr3RO6N@Wܥ2`,rjvU!\5>҅xj `Qq_ϭi]9R@rɾ]+6/!!9Xygp15:fWAءҡ1N=YQ08J H2d9S4u #2ۏjl!#;MA6Ң!kdY_H9L#IN#i vqS@;qMB?)RI)zTSV0R4s-Cy0]R׽8~ %$ojU;e0ݘ6{=vU;Kr ukcKiv%P9*m W~*vKΜ%?z:CLW{.}O$_25՚k/WIQ -F :pv'L`[Y3prR@c7TvMGX(Oi7;<D7%cH?@4JBjV%C4j-jVȥ53^c#|#fRړ g욚p@X|'A1cY"`IN<`|`(GdҰ5w v঵'$w( ai#u ۵,lx8+P50`쵥$U6kp4$R@-@ B^PE^P׭8('+rW я4`wB(EfI!dqL=!yJ4션_'{!H 9t2P' r;r T0 A(-#~Ak1ޙ@c Cz1nDgzMr]k<'20炔J` P/KE8RGslsvaPQV|{PX2m3 rRTqtQ3=*m$$HyXf\)ڥYy0nܝGxMR"1q,'4ھ)ڭb:|}OӫOΐF%I%v#q'RZl <ʼn葖 nI^{za%Ptl`F8q$g6O$gj'zyƮ@Y+;rJTDֹ{Hv8~J~[B%>$;:߬:ӭajI-xTO?HܯS;T.R3;) PZiZ{~VF>j,풜)P),Nv`A ?eKpNQyi@ʢ#tgHV=9JUoX>1jvT (GJp&t()qSTI(a:Ԡ@l}hϚƪ0cUhiLLP\Q|v=ޫ'\~g)7!+ B0yQJRz}sfT:ۈ{S iH̄J 8NJ|1X~nRŃ]ml)pYM\.'Z[/EI”ö'׊ijB]Ts1S= Qft{^*zc^w \uVߕ=(hS5jIa ̼8TJ^I., MN5Qڎnֳ_OH$pv1,7[gY/V OBڂNwI ;e]*BikP@<&UI añpϼ[\ajצ(,󛋊 y[(G T'Jؼˋ0眍KAwkĄv@BnNj*RC{@*Onըkl,m9%:oz֗PBB3󚓇`{*ML;AMS91`o)i>3v6L4d折,A.xVy=l$*T̗)! Rqկ43':\ >`lRh( g8ikrΙM5~Cɾ6\̈T]gN2qo <-kCdkBfFFHټ6F pqoճ_:iqm9%`}ɺ.ir&:LC8!R(܄jlOm^YӲq1S ` eqw]wΪ_>`-$/; s`[-v6hMIwdvQ*ʂsDk|0|xpJ$8c"C˶-ի_THDFz7_리;zr}Oy)ըMt6l-h |GTƌ4lmmDcj*\rTߩYޜ/-q)p0.џ7> Wh_!}dxٲZ9ݝԢra+J_JPOjv jpڇ ՑjGK-j[J7 LHY/]!Դ㱪t ]DbH![Ps ~}2W<3[3PZcCK}$+iJJ 0?ڜt#qdU6'2<~kYdc m][7L٠aC+~H?({k-5u }{:z@y'{C7:yntHp9ėIZ'Fۗ[c,:R'rk QoA]sT>ʺ'?"͊s٭ 'ɘܤA>xB\#q;;w8JnrÌкϠzUy]R czT5[HQqg􃂞3Ijs;׊42OEq2 kFI~ ;ʦE|P$lSJ@Ӝaq7OٟCͿ"DJfx<};sU\S|V|s4cu~+US_ڈ]إ\C\%<}wJV6KI8pA P'i~yEUP.3-'#?Nc/R#NoWOYRlwAE'YK`}4sϨfKH g ?ok!==ԯNǑm!Ĵ$5kV-<$ ` vh|cic q;;}^ZzV:iq.2]+z 2Vy}^ITsZǣ<7ڂ>Nl}1+Av Gw(gźoe)KpdQ}.R[]n @~|NN&"t;s:o'5jٔ,JƥP%į "m@My?[5wUQC)Nʞ[ l{GO܄: Տn GXmkyOM;'/Fan%si}dKeJj!mpjk/b#sʳl*h6)?UJޜò]FT>Ap{\pVb d4:UmvYmӕXpieԞD8eOڻ/'g$UjJ' ytz0)m|I !{ &uksdڐ8RYLm8pO'D-;'{±GN% c2py;}ރy'V5P@KI*jUn8‰y)y蒐| P)]SNIL}NJрmSeJڙWNޢ՟Oo٧MOKChjWVRGڀ>4mQ_o!H[%|U=<B]B&Tҵw*n[dnTm-."jn *eoISt%* ["xRP͞PM2aE='CKHZ1%MpQ8ӂXg( m&)BY#n{ӈ,pIL~2?WQrHif8wL'!$u6NJT9EF[d@ǽ:U,8L2")D)ϽI8S3Ke~ %I"^APBgu)qKjCh#r|- iGp)BRpk0&}סdȏe8Xsw^W9XlMp9cVh y,rb @yEc" #=g;@QIdsYkyy , 'ܰS#tc+ݩl'*I=SGJ<%Jq+XR?P "V A9c%y?g<?PqK6䔤1^0>+bZ);TS׌p;-G5E!?IQW?zL%b%g'rI4bj Żh.c99pUL/,cB/WAK47Z*uyy;ASyٷc5U=oNFu47;c7_& 1qs+iòzΒtT޵R:w~Íd{q=NHN6cA WS;17Plyw9vw7M\ {l6dW=YW_^7Xޚ| ke[BBxJ@ p95=Y ]}Mt,ь4c'lIt6hj^bvPV ln2{Y8jX㕑as!(XlzΌd&4zu6C\=U(HZwm?5=.8mfVI7PuMƝfɣMqa7Y֙Χ J#8qRjj=,kKAsp.ˉ>HݲjvJd$DZ{TD8Vl7r'vvz\R\a80}93q$֝4c>ޑPXZQyi;$LKee8GMzfkExk%-? y.n;mx;XAΒpOrd":RPWK4.oɧu%S#H*o-r))$X56^QsoתfK5\@Ƒc9ӝ:on}!I2 DIh իkAyklΗݮ^SaRWSu#1)U3v҅a=2Ogk:MAGKF=KP7Kp p>J?מ+BuBVhz"RZ\iYc)$ Ac O~w_` ֑%:pƙ3B>C)iNxû_:zr gvLv0,:8 {85vgU ,qp -8=9-\SA#fZ KTR2#{LcOpL#+6#ޣi<'kcCXѺ9Z#q²A#+NIv F =R,rorlJHXSJWUڴ填"ّreIw) #n9ϹR u1+Q,->9R5ë`ޯ:7SK쵵ƼH)˲nNېCxV_\ov*(}mKuZ{EPd|pnckuUJX0R b!yU-M^3Djò8[ZOP @)ل#iTmӴ8c Lt}S1KeثnRwoNԽ=Qdn7{b;1?OAZW=Q񛎁3؈Sdma9Y?aS ˴rIl|e`?)KVZ,VH`y$._Lc?ʶړ؃X^.حc|rn n6X& LrBX@'5U? 't]yۭu5юPRXW %8T%)پ]e}PZǗ7-h#ӰZ+-FnSpl٣ O/\^Ԉr_Ά_tmzeYfkttwFPvܭP{Unw6;wq¨uTw95d7w-~Vѝ'jluܲpZlKy 8GZ \-S@"kf9>n1\v\KoU{4R/}1L:]U:tj`$4aՂI< ܺlt- lac@.Ӂoon;$4=IRd9s;Yĝ ʁ[-5;D8+K2]ᰜ*8 ԔuvrKr?OcmJ6FEL2p@9c[KItZ(V&)Bp+>~5%7RnsBl_sk#k^yz?i3j%&^Hq(TY;§+y'-n-!\Vj> }<`t⟉ )A)ol $\y E#b_kAJCsOaVبP즒ַl =J 7sǺb=QjRp h*ɇA ϲjIiܦRۚU3zH’#ۚ[zA؁nc\ͭ:.CB3[Z׎^#uänȎH璜bMZ=EߌFmF׀ מ|g`+֗OzܚUI 4}T*Uz6M-?n&S2ɷ)NIǏj*&JWgsN5(!# d'h?9|&t\)x&2r+~vQ dnGN}FBR R{40ˌJ@hjulS:mC!G$=kv9MKHIrӲ Ф1K5 _ $5a}bhu vzM&`-4wd^8Z׷鼘JwW+1dvz б$ PPPW!AEdPŨEvP$8(+ ^$%q?i셓 rR X)=;R@%fJ7)ˇaxAQPJ PY4{KGն JuSI3g> UM.`ϲ q.9PYū_Hj6z`?9Ү !C6ޥt2*v>y2X7ΖF<$+-ﭭq 8du,HJ%8a-$)]$}Ua>[q(\WyL(sTm ՅGp˱iF}qb nnVj$Z>Il69z2M%9}\dz~uqXu5S3'4f<.vLGs!iG˜)2e74FqU8"-wm8ݧ?Ww+V%I;RnH@g=jυ[-h꣨g8K0摸 NUV >$Π郥:m6%R`* 4[Nuٴ<z_hbS\!l1SܖF2E1wʠulٗCnDTvR`! )O^y$}W(冎VaZH8SHW ^mq!p]':v}7Zc]]T)8RRJNsjYJ 1[g.6+|v]=/v1dyp9U FGpah|qYSk#tY=q}M O>x +yd5_Z,R1qc nihavg~=ʖ_e4% V$ReM60\J+$1־.o6BFޣageD}CyY0trx.oSi*3D+zo9iyj l1S6d {14Z46=b$' 4sҙ`Z6_icnpD;U jdAP5 b {C e9AEYIt,xkp$!1|cw[k_=t;Z >qIkr/a frn8x׎̰}BONOw?+D.!%94ϑ>w]g붪5A5:le]1 XTr22N %̵lTty%.nN5< 7É95zJꊊKCϮzzzǯu{qrr)Q-$X:Xw|.פo;~"[źtU ܑƠ q?Z:ӎuԌ}2ܹ!CGusUN Q֊{|ewrX)i;Wo;wSl֎D}KiB@yNcd~?୳F5T O!??R{"qŜ-Z>yN&Hd܄~-n!JčE19ˋ)9d:ƥRNlܫ?M֖NcAJFtCXj|g{?k-/e7EiS}Wt^yAk%=żP%{QQD lJ=J] T685 QlMlcYVXܵW lYay¿hW8qzث]MKKl2qP]qS .Җ҂ְUHiy_a^kY\nI+p B$&@O#, ߵ1<8RaaԕK88DJl#h?jĴj vއ35% DrTfvTT|g**}UStK2RLqlM)X5B.m{W_fc 5WEP]YGjڶ "7r bz,,#^1H o3C (#mKu=x8Vs)o\52ۉ)^2s?mQ zR͂Fr Kjӈ+@9)黔>FV6 jVt,%@i+[Âa=!ǥ%v8ӌ{g8/ );*2N8=4ލ` H. =k.޵㫾bt l-.tKAi!7)J ޾C:E#`I.p:FI_[7T9JDt$4rv .ӱpƌ/=*]*%:T[$T?~q"䣖ZZI\#c{p=1W AV;6[ *QSjncA9Wi?uZEh- Ur{jGԥ,p{PCuAhhAK:[v82UkyH)8*W-^Dz1g]:/S]ZwUAޅ 1ʜ$cܜoޠfo zN%g7@ƈ۬sS.=Z&g\t`Da.#|<./M$9%-֎TԦ'{1>O8J"IV )SIa˺ ݤK|Gh-#ݲݟU<.,wwUDUJ?0gi#a\Ijm=FgKD^5{cl~knZmwʅ#If(qKAP 2FH5̶Xu;9#d{L6fFqZtOն-so[)%  51V c-Ȍ8hNO$ $gu:*WVռ26(.ҷM/}ie»BZ鸃 c^̆GC+p<NUDMeJAuMuUUh[U⺤@p' ]Ϧ.,_1:?ʀ^}ֶ0x=|.F7D]m -Qr r[9TYx $lsHsI# n{s9U~őS6)-=\.뮦]kUyPYmon hKh+Z7V]/_}dq>t D#g8Ϲ=LzIڢH>eG @U;kmGP!#|i邗y"䓌exINYuwfƿ0vKo[ʆR! KnPyȩ-;/ďk@nֆ1} q߸gnC\w' < nA\wM8$R5kv`>/8LFSq?oF˹w*wLpNJ,$X"$e{?(kp6}Gm=gZ+ejōNP^N%J%/np8Bhx ٸQC+}zINMGT]>SZ *倨Pňdxl\+h:J85aZ܈*jmdkaFK ng:L6Q_R?sWL[:p5,5$q KH5'a>>>DuvЬ])z3U5L뫅^v`vD\11I H r[7U Ξ[&*mn2 (n|TUR6.ӧ'.'l vR}I-5#~35h=ÜLM;nbTSjKdܐU~qq`lJ[Z[Aސme@'k\SU,nyP׆惬sF] nC*emer JN$gjrjؽ wUتlC<&HȃKѝ-q:(bkd.vٽss'0T:T,)fnmJ0_yjH*W=H#!qjhҺ/&&ֵNI#y9;6hN9ڨj< q9. h ~|wgľΤ6xOj'm nT]5=1je#FewsiS\ 4ar` kֿ7 U4TS,($\n K6]l$v9ǑJESFp2sp?E@RGcA)fɞTUEHޕk|-%ygvHW-E{XM]db5K(-iewBu@P=O#9LJa,RWe"{w1s>9|r)ʒ!;'&!M+T%hg cc,Ak;aJaAH< uRR6A\h˩t"8W'#mm{UiNwk=e&*IڷONr}Aҡrv˹m! 5AZBҦ<*bu|6]ZҪG!EC);T6N0j)dr0+}jRc Wdf5\XH }%6~{Ė2Np|J,&!?}HLݱMA){I$$ 6-oqb!IPRú̌Iϊk*#!ϵNF[^ (NieZnqKdیk&$)*QRdlGb $ ҌdR04#QYrqXOlP+F;JkЊd"D5됼n-yNNqqީE\^'s?Hm8 ՛Pvm+Vt7f}Ώ  G 6Fqސ{RkdQ0,dq=Z2ptgFT!㨱.?#;̀#k?j`e·I#$6m8؜.å欄RK4Vޱ2"WV}+O{kP[I`1H::m ϱ V$t*zazӍt6Rmź~JmH.%{T3kd+o6]Lal295cN;S*+(mwjZD[@9-hswFhǵWmB!ET@F R$#jPMXر` Jf;##%O>-Id#%3PH +U.K]38qr,ËN0?Mҗ~aIɦlnN7ZQtJԕ:}Rtdk;/R ~f|2iKw_杺7vV< Eo*@m(RTT1ߚ/--ȨD2%pΰ:}lO^5S?_1e'HjW7:mOP-$)mF|$DBHwHRenq(mo<n$֠R֘Cw F*9 t@{:Ctrfi]#g^HDn(zp╧ rH@uf\zQ;5CN =/{[s$oƼg^Wnlؖg,r\*j=;βjkiS}S F6|gRBJRIqUN뚫e!.]i#s} 9jϯ7SўK?8ܬ:tuY uT' )d%d+)em͚YI$=G7 mDaIN*FD`ioѻ`_#ÿ)g:=|q\p=޵S:7LR7˵j?c㟒yT74P잭[ yFcӗ*EG'WJef*b+69CIK`m![B[O$%xot gSV% m+Iw YJz&UR˟n V}iެQ@^g9V>s$) _ԒO?7Ee=&]$x1}#g{ F='~JN甆U Z짠Rsy4H܍\>Q/蓶|ۆ0jZxEr5ݤet~ )l}W^n\m]-o lg<䒦ƮU,`gk[*F#W-߳2WT+~%-U.>rMĈt*eN)mJV{ [a3tS)T[ іeжۧ'Cy'te 3ROƠr{zIJ27v)')qOΕޜ'M!4J%%!t4i@p<%>)@vh|<^$ +I$W;/1Y, #<H>>VkԎQBBYY f+P3b^V/PJd,Ҭ9$$OՀ`+~'ږ 4ebv^4\ ;NIU.Y0gBJ#{yblmm! Ӊ$hB/JG 4eCcj!,mCy'1NWd)ˀ g9hd7[TF3M: wI'y<yj `+'dp۴p :hQJJA1m_i=fZײܻ Z`U݂R˫H `Q_"~w_mDg~qC<$Mo?uU$ΚXfV'%FA[HA ) 8vM'Qܭ/VOIwطPCYY Xs\@}%D/ti]a};hӽ8jhQ'Pܗ^ǀg=nn[[59%cKq8HP۫CƗo;*FQ5*t 0o;Txsf&S8VJ#l n.ZA8xm *1Y7JVTqj ` sڅ~[Ӊq O*#7j=|7Jhsi,nׂЯz;LצX.%?B֞@Plނs p6u^)kJ_K ]vI۝'{z:ˮ %.kـ߯:ǡ=Uj)z[ >:C O?R*ڹc4eN\6"\}:1$lZIx~{sHi%gՖL=vfEBnXTe] oqQ۸EۮJ-6S2j<]1[TEi!9FI߅KKtюuEٯzkX!_+>$=gp8V~=A.WKj32S ښ߱B3w7;t0n 8}Bgr:|QNȈE\qw!rXzh[ah%8 l2r]40sd[*ok2Ii ?6R)YU)t}~ZbtV🟞ewl?]53b- OapG3`@;VK?Սeu:zqYT. [g欽ED~uҎX8OzO쫶^'u%TrJV]n5&3JH m)?5J, ERFL~v#M[v:ƞ;S;ğpM-(%)"aVKEdŰ[%%6 Mmȍ͐aQ-MF(̓QLt/T<*UP8=gTtpIa8@%C{E23ډjiuRV3u>s5n {oIU=ENyy!ܨ^ڢ,$8V:;qw]-; j,DBmԂwVvw1`}3Ζ@Btzn.,6\-Œ8HUGSNgn5p AwRJs~*mcVX48 %T@QTwX#GnPh!>'< Heue;Cw;:ˏ--8vㆮ/IwRJ@ؒs;ljl4 KI/ӜmL:vK.ZϧH Q4Ra=I M 28WMɒV#jW<앚 t+nҗ g춠=꼬 Zrp8JSڙ9ȏ;r@r<&vZ pta& >mrm39:"Sf(}5Xe_R*ߒ[P,S&DmH%I @Ub_F88B5vg "X|ש$&\%¿(ϵm uL/ycO3+SaFn#88|iZKF6uP[FT/dXK#껨}ȫDž>Wb4vXu0D#/=|_Q5gV5\k}C=})WޜQڨCD0lWY1S`jwPPw>Yc'8DRd Ye> 4SqעD藆0(9Y NVߔLm c $Su%?I\krTM.ר郆 \c͕CA촭JQ#EB@a<k/3s ߕ'1Wj~{/D0GV81X]=MGu .Eg?*b+(83'4B8OQaqQN_'s| n +*&zY<)Χ%8mhou햼p*ڥ6JTˍ+Ӿ:Tm8Zx!MD Μ lqV]9Oʾ60Mk]Op13<8wT6ު6=\5BTc'w}87ֳ]CWL*TSda 2oKܩ̌$h=kkgҋxB[A$Z:ʮJ=䷝?rJJߙ<.|rWE$I:C.DIQWӊETZvS}#e>龖ѝJڴMJKCAI>Y­'u7ZC3gNq3TW`5RF^;u[w^k ΏL\2|- E& ELUm,dÜ6!I>VUS#RQa.sBYۂ6IuQ:cS ",Xn2$wFZ7*IS{/QZsZ[٤m/:K冸qXvDן.-UhOrH0`'{KI>AKI#U諢`t%hlFؕgOAL.^-vlr*v>"JrF15گ+ձ"x세IOc|(̈́$:LnOf.h]^׫`odHmnK̔+rC(0Tx*F +_EEnF&=NiAdR_%RoH2}y츢Wp Q%\q޵D Dt餩i6ۉUh8YP ds ru [Zn~8ŠՑ؝j5;8?NZn{󟜩r?{ej d Q=xOzRtT]d/{pU{Ƙ C RG0CK},ou ;ٟG#T2>=cۏL^*.^QCHBwxsNp3)O!v9Uvxw&dݠr@i];\vH=V4wZi0kuC;ini~j{ dߠfD]NNOBKlrekr% esO|SYbUu7ldg\=iB(_)&ɗpٲ^-*[=ʔy$ZV9.qHJYirVk#*OAeDP$Ō`5Rl@H\eg岅 =+DdFIH3Ԟ{RS IR_u%rk!"nhK)JqLle#Am sԙ'LJVT zbHΞ(cڑ}@줩87g-9m?M$u` lKy*I2eh I!ږO55` Cfh!Nm:yn;ЬW.@pTV`};0T{^(zX4P@K| xZt9Rт V4PJWRKӱZVrvWmԐ[ [ZpIO!ٻB ;@|y$,;6{ 8S{RT9a!Rr>ڕܪKNˌR ݴϚ@GpR`NsIqc)"N iSp•cg*UTrMO 8l %cM)sb$tm RLc39pa &FNS)%No%J5jp"rQWDVM`hpPK;#vY7n6vD-ͦU 4!&0مzJyiUߥ)&L970q@|I9Yl=eE{s]!Ώpd ߅Z_~u}IZAy"K&heh_( mcm› ?KߏT1wn _5ʌWӺmZ-W~cpσa[B]-!DNr*|"<68ǘL'=]AS#Q>'X:gLko_WWzSȳ嶕bz#d5!#rqGHkT*/3KLuVCA Pц%`GLM晴W}; `vIHVReI YQQQ~\{gik2VV 06RT,a4w5i!՝-eYW(ߝԽiq)uX䀐0{ qWK5t 04n^rIǹQK)>6䆢nGF sFh1(gc$&-_JKC?z\[O#=œ !U 4u_ݪwPu4.絺F!2^ԩ89i)+O#GVSGrqR= *GXJXMj*l>7!r웣ɸdI>H#|zu.'֋-֐11:ʗRup1a䛩y&27GƷ?]het h.{$HTPRb(nU=mM1RC-)}O|/fT7!ˣ$-ԃaq D1m)QY*A}1ZyyxnpaiO"^.-6F[INNUUzj(dWwJ7 Ys0HԬ"(Ѻe/3 I!~Ü%{)dNۦMOgԆagr3jFUIOIZ꩚SO-<+se8xܾSkPflczT6xh+P**Pt n1-^sm';I4inV1nWR+qo.?qjFFW^?ޮ}MpwqSoP)G_7z<Ǘ tk&=2xwG~[~ c<i.:Z \Nu1G׺׬u#{$ >6!c^՘+E-jlu90q5zAZ|Vz@;/ 5)7B{-+lx]I :f21%uG p<)Z)eL Y6_t{l!Yd)ppRy=黦RpPH:e/+D`4Rpۀ%Pi̥ඟdPiSvCu"h+ۑQ55-<=>mPF5)՛MvOqϵWnYhVՋKvm򬔔 GQCiܤoD8`9V KMVZj"<کYJlk!V@V/Pn 4 AMMl!(V5bUS|HsIW)IOIT)dD\Ca1C- 8cZpՆw[TIV;uDnW$0vM2#c;Q v%)P$YO K;$)Yf,pkN@RKs c#=餀8IONB=kN0Sj,x%Ro>!]KKNs~+:3Ui ̼aa ;{u4aEuOUDA`-R=PugenVW3GBV5ceU`e 6TPvOҿ$jr/t("G@=J-6QRKUbG 51xڤհW I~<<۲4Ĥ(ʌsrAQ=dӺvIF}4v)` 'Jd&VRjS6㕊F5q^=mx5 }תGH"BRW` 7)089`p~'>-큷#$UBzxfsE)Q/Q.R0AJG SKXI"]$@*Ћۑ: }0xo^TLՊ偁*W.(-4^3Q7RT=,ꙝT$11=?@HXy3t D6; ̸+7BP>RUtokoQpS]!@6TA^o) ylQ?a'"V8KOO~*ճ99]Pr_jRlsu2%gNrO~xԽqԗ>q{dHh!hW|5wܮckzrL-aAS%c>kǴC$VK#ʾ\]>=A|hɹG̉ yJqgBս  @R'3${XZ ՟Hny~ $l>?>T:%jY/ 鮩GԢ?lRWo soK$mC#m@) "k{.5:mzɸP>W 9~jQK-3I-(wZ0>!U] 5"6?r6GX`H*ޢ#SX6k9ؐU6"!˼ H Q$dl ][TQvx'utLo ѺS7k$ȱ`'9>º'6"T]Doaàˑ.>uNn. s?NJEtj hVkdCWp0|vjurZ](~܁ & r9Beɒ2<(]]ggld5RHsTd[XU7X$2T8;RwtB/SZ3-<ؕ5TS `<f[dd%H&uA!$( !G_S62Tsɨkʢ&:՞8UWEnd17ߏTmϋiÊ0ZUϮ}xjb\+%-MxTn2R U$)!\m6qJ%|Si(䫭ʚZuͬ%z>8@V0~,lS36lU."YI#*4$na ]xAZ mt0ŶIc9V]ֶ~e.mI>jS8xSHR>m|PHv rԨbj*@}Tc`8HَnRT~/7enۣ ,Mz(xPYd&q?06X3rkLɻuiQˋQ)ՓԎ?oQiM\O?4" k:Mo_'JT5< ڷ[X:sf]X^`ew(jNӵ79q8VD;_;:yޗ0W ->}{ nQ?T;Wg,Ϩ/W}QtxNuHYqYZrMtպ X ;CXkN^Ssqz36׋8zقԃN?HA ZlЀw O9*@9k򐚘qFQ#4mFsԶfMem|^ #= otgh*>HGiR<`Jv֦{bk%7Y>)MiZ"xord׆Odtet sM"mVR)'H$V,IMR6K D^ ~J6H;r(qSVNۊ\ث,69V}IM^0ySPR aqjӋAHv~u/M+f@(ʾªK[v+BJ#ک ӾFO7$*r+TVNԥ881Zy) !ROp)[+jim!@uA$8.JN=vۧmԒ KyET?|,$~NJĕx;UT,`w &cvqnEݙԀ21ޗ# x)3EGNwiHHOeR[XHcI-;n~HٯVb&*}$`lnd& @G|Vm[Ϫ#H>sm̑$󄥲qt7")JE)S6[n|djK![P4O$lFmDLlwT1 <+ %SګJ hXCU6J-랛KuUdva8UKX# NAw|ax[a\PQ}4۷ڷMiLypVP[JwiX-Ul=*6HjOXñ*WA#;&'[I%@%^G @ <$ 09Pl K쫕P8 %.>ڧ=UrBIam24'2^J@ \lִTiPx K#Ze gy HnD@qNRN` ;NGJ5;)HW#*Y>SAK{nx. ĴM*-LҰ H=ŘbPqBS , ĜrsJ{$猌V: Bw^/BRڒ^*Pp^&bN+8RHe8[.Gy$)Ix>œv^XFMx4' B8)3cspRG,RE)44)=9+*;SFJI;5'q@7s%HJv{_B>8 N@ڐ)q5/PJJ4'BwJxa[ |W9T^Japln@_ްE(a ;0Z+wWqxoi $*>5eJ30-~6;8HVZ^<)kDT:dXwj8j?ys3F LFJ!8 ƴyx yC=rKe# Nhq/=7fkk&4t}|5+š7Ykn2t˻BHt`TAIGm FNԫgS**;0Z3=XC?7I=dN)aX+qI>s3oHwFlAД:P*OrSP} ` 8Ors.0Q> . vu 8'pH|֔fdN4`ge9MpnU!BpwWt{m:\d{E!;{ֿ(cj9m%s%O[G@BƠ6 n@qam'pxTDrP${sSQPNJߞsF2rxʉSpUDѶMFl9b0gBB1ɤw{4K!Dlwj]X):ܖIo҂ A&))W5*#3! n@3L!Ah3P'slG(RU;!OdfQ[QߏTʛ?Tʊ6ڔwRve3KWu4<ĸ[N [‡l%CٲK#_;uH&FH*L+5A Ox*pw^5  c sNcfNMG43޶ sJFFj ViM{&=+k#<$g>DIg+0W5zC={<}cW`J6nDnyk(N"N TByjn9Rj'8L*+V kh)l+:rlBTWmhƕM{w8\HX5{#rZܔj#wP3t#<V~I; -'6 #,^!'lŨ}@BbTfRQj,̔)A!U?-D$7JŷIWzɺ'H!944;Ka'eN,%)Y>S=sJ/$TM,좤~]VIi6BZ-Ny@m,HdS\!#' -eyjrHCĕPF k̯Q*XxJzd9Bڶx9x,S(wl[ Q(#?B4畱/ J[^ )[cqGN#r;{s{H DbJCdgǚ$.zp[Q(1J,o &CXuY;$wƷr&NBwa)ae@RzH7*VIM(w 5lF2y N{{~+viy -Sj?HQC_;A°F$cCE=BcEB^l/)=ڢdM#\O_K楘Ռ&?e0Tdc%Rr~ 9Fd9| F+8-0\P׈[L"8=t,m 4'G %>=MjՎ'f8lp=ּy,ƶ L4:Ҽ~հ}yZ69]j% M{d`ܨELO6< u5x+tNhQ[-Rc9{Tѽ9);u8`.}nMd))h^mXHVȨ0h1JZqc+Q'WC$,C2Yq24.i[qcVΊǦ @H%VQ6GVw]nw*5S.ڹէ!qڡ`u;k=.P}5Ue^|4~~ Wj::DD;y65dind8K2Ũ̒\~~Ʒhiˢ+#L]4u}O%ę,Eq(yBI>SZx#MVtg}83 1J@lؚzqrM*QIKks;F{f)&nIr LPxOus srxvǭMNAXP)t &A#t$iIW?2:Ntg|RROv\O"S[:㮨TIQ$5#5@Q_9qZVnk"@J5rJv/)hR"dO+42a9ޓ^)G.xXI$f8԰ޢJ{i2² +BFoh~)+$'viS $\d HVQ8&a!17r@yKL$^ix(}ɿnv.܍Sy+ )OVN)C0L!' s0Ϟԋp4,M4PҗVqr|SgW'p8R(`BSQܩh-Х`B\2c*uN6ҒQxMW.npRPS qm6'*WZJV27S[}+iۓ*͔iN]*BK@ʱ-v5Y9z{'SmӵAUB6``zh@SyW*qzTḪ Ͽګ%+)=Tk$LօomhRSkq٩DL奆=ȨFq& JF{RŤ)jI7Ąe,P 7'cbn Du!g#6Vͩ}ѴpSa)D–FР N1Tԑ4$`TҞ>"ZҽƒSy@9›݄YYG(tDz'U HHV:x[)IV| 0e7  RU){Ե;4j`hTsL8vvH3U(Td!K[waF*_D^B".-Uy6q7hRӦQFɱ%$5YQRt8 noܰ[sW\OL~yF' 1Ҽm#G+`(o!C8nJeE8 #&Q>*y䃂ĤHC}׋oR %Kj9x: ~Y$~*)%sV8X+fc ~Մі⷇B#=#CZ MZ~y9!8J(+ *J>w%`q`)hJ6G1IfbO J0HB<~F7NyynN’3 xNLMYV[`&ni.Ae[3cH-(FFY!԰)KJPJ Z('t+ZVڿ1x}Xr=)~ĕsG2, (Z>(ݏX$7_OP];Vc+_ӟ n lО[L Tw wI5ZC;+ӗK('j2j"in1ʰeD%LWK64w4 2a)ikoyoH/1'sjl[k'CR[a\]9 NzReqh@PeU[qݦ[dQ? Y a,{ogPO#R\ƒ*] @ 9<=KM#<{o;' vVlrqb eC>٬B5Gr~W)1*}+[Kp_N;cY,PԱd;~ e=r U4~դ=q]\eEEY'kRWX*etꎪX}J&[HO amW3V6KPe ;4#E$Ϲ>5q ;}Zh[f׼#.8OUŔh9+7-ꆲDHm0ޢ:N^nk/q%U:SSZр`wGBٵRfe >HI+J.[wb @H`UGTzQvv L0Wϲ>R4z8Z2U1df+lqR>dA*~+P8Sm @$6ASw-棍ڞ̤OD>isVmj7w?Z4wW.{[6S]œ.5 )aOd=g(-1{TN N{U7,Ko~1qJ̔NI#&sل wjE*Fqi64' ra%a?&fP7c jzRDBjVe$/ $'#lD ?o)F oĹ)1^bʨ'ڼ20e$v: ?V9 n q ɧM v+R#'#ڳybk^W &1&\|R͘6IL'JSҕV<'v#@I)H2O I wL9N yOi'=6j6 S8JiJRN%? oh6 ʀT4@Qs9zvSq@܀)ģa5QTRԬe zV<{c( N um`,%+NqUڙ0vR `e)bYODKPP3L퐔(* &';N@"yO\6IނYQ$jCn3-d1*2_R) 敊w+(-jR#E\X$yR[Jj]gNJc.vk=CAߕK cyQ9_iKBhIXņ'O[v'|TS#kNʵS2-&%JIgm@wR NfH[r8)##%,dLtڶNНT\8 _J"n(汎'5zc䩲G⥟ .$ɢjBqN)*( B<kImmH?(;o4 HS$/l=vPFg OT鉯u]c8asUsouĺL=wy}'|" es\|ӏ뭼VG[ݖًIPK^Ҧ=/vgڽr0e*a, (ԠcIJNZVвX`%8  iIH6p KR8NVaYҌ2v="N9ȥ4I^7p?ZMnn~ Z'^ҎTCH'Bg呓ɣ;@RHdek)У+u\$dv6+ַ)lhlGPS)K# [Oläp@>)d,:{'E7l` ў=!5GJ\ {Sd Di`:y^xqA: $,RJր d4mͬfBJ&pKCrRw$z9)ˎRYL}C9] 2μӧ%텤$4u=5=szU몶 I{.c]@Q%z}Y=JkQݬ8kSͥ\m`qƷu$<_CZAvׇ5ϴu[C$%6R 95U馺@挧SZ&b3QtxCEcu3xCB`etYƊ!G~W`Z;1~\)&]&j&Liu{&[[F288 u,|Gmlc!\R+[\Y@v>\vf?-JBJw>%knD% z TI7&# zK\S&Dd؍u1З]$6v%:ܧQUA58 mhbI0p3zyr?5wu,& MiV?oKȜέ"tVTF>䢨U{/1-~c_5=vI,`5ʴ/zLlBp=<OT^Rnk(Kv@L}:vw+Y޵O>*W['s2;\S+}pVWi"nR60] (Q,`:?>ޚFԤ+i9S* mzpil/<)AF#vNSÔB5yZWx*ck6NhvkmxFI( heHm6d~95W^qJgl!8{%[F0cF\%ZI'Lt#}14­ѕ[(G>2`PToV9JHvH.,8|py\I'XW^ZSq/W5)/zc=KyC`+bG+>K3Mܖ#Z|Ecs1˗ym{ [.wIm+ 3@?tO/. JwYP6ԵQ5)I *4y 9wzsvBOX M)"F=/N }IIYL~N  RB暙'F#'nwd4^@Ÿ0;4,Ѝ)X[fA8ZV$84_)I=}fȓZ\k'3<I2Ґ3JD0q޲c6x%4Uy^hZim޳kI-8|OtkL#~eyk# 2/44F;(Л!HQQ?ښPR=1G7rCIR8rOTt6 Q ѝIڡ+ةpiJӸ+TUNBr [ѱ RqU ʐŌRRSt&lIIǹ¤jJ19NqR e4ާ coSe:c4 IVӌoz&<2rUj=\Ly)8!9nT; `g5\¥ lza Z $&TM:tX)&Ӵָqӌb*&QՎq㥵GMv*RsZe)h'iȧIII!q.:Iui).ÔVCj'GT# SȮ[* ce3;lRillnJhBBo spBTXj;nZa00^S:zH2-NL~}% i+9"jI*t&NɁSI6\tWq+S/)ed\O/v X8LrrG#9ZHZ*}M,YӚlZl0j DCn~JʁnGStzH޲lI1NyYEJ_5E6h;@$Rm{Z*kVihvRSSJ% #R'K Nh("\?%INӥ¤u*-v JROz莜?+GuEXYouĺS^q?}}5띯vH\]0~tFkgYˆㅦoTM* mg'Te#N"T窡z>ZU:v?!LEQKm!n'Rt$kPgHҙd?%7Rxޟv҅ELVҩ )i$ ҥBķNɛ+R2SYrѐR 3ȯ)$g *] #A *RiF'@LsFI;zGo+)Jn5bVoEDq#{=Ŏq2REBMXb0qNP5'Rq'&'Jn #~N7QGN-eGk"^>v;ܥ͖l-)uJW޲ӎW=;jyIR-o8QV~ԙ%(X)Bd? % sޔleHxkYRU5Uۥ)) 59^rIl~I~՛ g Yp#>UNۇ< Z2HLJ?+,Q!d/38.Ne:z-.'9y A<-y8c ^pIӌ{S=# 6o\AM0 X99H^*X)JB')^} N0kF],Ғ$ֽ7/L\]\mGog(tCTWX3Lvjiٮ }xuo/Yhפ/𱻄e43sODN6Q8 C]j5!8 #j6^;[6PSZhIf>D2PtD%sN&T$ ,&Nv `4d4K)أw-]ԯ=E`,-kR{_W~Z!`ZܖF}gR |*IaiϾ˅,c s6R[2 9)k0S)٘8U[$<&8H¬pnLAumO3r+DyHsHO,qSҔzn$ ɪ;7 s}@0kr $`1Av|֣qq)OjǙ(KKNO٪x*tkڻ;HQH Yjm dJgsJ`n Q0p0 eL-+HD.N]%[Q*nDeSw)"E۲$dS*)ndX0.iǽV(S!V؊}^]k*i QۂSn>'!- HrE*U)K[0>I< %(ءGRl1yʎ #$OcG eN;4  vOzzR cH`=89#)4aY)?M ;% zPW&v^J%YSwdŧZ$#;ݸR}c /e%\[)¿QARn JʕsNC ~W~geeH~,edZt6ڱ1sJI+ vO[Z@T|8<={Ry81H1|b$9IRNT#*Ko# 6Q55IpvO Q$dWj*I<pGQrG Yo}<+5 USv>霒)ZpP`e T; ԍPVHIfP*@ϊyI)&>By5\y&rzPbJ0j'%z㺉\ <}B&=ǕcR`FbqM NipЙA-FiPS8RRv%lC*6eOGRFFRXZƍv|$ Fr jn =cl޻%( l{g12A6eʵ@5@Ds)XBB'dbv;Ij =P sʂq_5tVF=\8r;'=[A׽6Xm (+A<s vXV`/][>MX-EuwEx`q?ϧ'ou:Wd~]h.o,<ZO sJB7d\QܭjT4c* )^k4/9:R2𡶲5sp%kXVG׺aϤXO dx^@!6J%4#dٍ?(xMacd~NB]JǚBHOizVخA[˂uKҵҜ2'~Ll+V+S#-WQSH3$0|-zo9mqs審PT Xb:{rIʯm9ʰZG3|Zuitn[=NԵ=NqU LUMϾ0Ï0k#?TeĥpAK?wQt,h /_䴅}8OVߗ۫3&BL}Z}RF+YJ'RnIV)Ԡ|”QګU idjM@To,VHiO8@?ڜں^t ׅI?%tf=SVWNHB릣2y`2|~?j6_Er$#~iZb&;k+l?UE׫ǵӚmH )HYr|t~ X;e.PYy6JbUJe)d`T]cJYSsysefTNzzK9+qeJ'O4k +Ē Rm{f W4R$f RܢxIX'q\2SRи)hFO1b%;q) 'c#@dT|eH0शPd+6kp2;*QϧVs JIJ9pdIsg5MqzH7qKV.hshBOޔ)#sӌRѐ~bVj̿Iv[H+XBTJO)c q!#sYAY!) SzQ8RRk|-$8g4,:l%'WEI3blGkjB2~$)wLd[OfRwʒ8}20 {TmK)㺞A a;GUzWt“288HOE8cf=DP3&id$iu+jxp@vSh!V 9jY;&LئQPQjw j\ݔ-=MNWJL#`qL\]A#-KQ ׍hmwɲs NAO^G`*&ag<¶oRCk6dyF"H߲JZgI ^rHQQ4=I-1$-.Rzg; Xt$-RhLpZУ۩`G9X*fN$UjdqET0ʛ᝻v*[} piNyj~vn jw5>~-(-JB\gO+}t 1 [_2\שRIbIޟ^.'8RAHn:0'qk6;g zƎwE;\q@luaD)wǾ>t[@%Y_JޭRcFP]F9#<pʜUҠT8 ;V&ݥ3He8F\OTP3[U$y>ԃ[l%H iQ>+=d0C3J{lYBUJ7Lu7$q)6hS+YDz`zjs* _?)\gSK@!jPvK޴M@~J)Q%l')3PxDeK( imw&zqncϲ R}8>tڧ]XKJJI{I(ּelZؔj ưߪS{#v$n"# PVđ(Ȝ[[\|{`b z[ Vo5/g/s6*4'NhJ4;{ ]BKiٌOC8#dIn}4 sL&ܝ!{z^l#yJ1מK$K[qYwdb&9Y7)BSvv?)會VKʎԵXpq-;s%;npR=@B1ނI( CyR+N\19Z |s^9ob譣D6P# Q_\^}#,%cYUzբl6KH`Mu?FFb≥j1 jVGguK 3lR~'1l7 ¢GvӜ%uM84٭TiۍF9YyYg׌SHZyNܾ]ps i)q ;0앺%{$?|9{_KjJVQ39W1r]R2)ԔXK&fR#qڔ}ؗXWfmIg @O52-z2%6Msˊbˈ~" I ?!U(mW8gS='RH4+CZyڣn?x+K08lieMI[?&fRyrV(*dK0gu0cU>j\' I(p1WNvS+fRT%Va q)$ec3 9Ɲ~Ӆ.|',y;#VJA({Edӵ8QU 'y™E$ cBOlj)Bic)GڒkY7┤q)Vd dI+RڐG5сͯRiM!Xd~zV *N+)67^%m c$ϵ-[[$g:yqxX線A{Q 3.,(S[l@VHpmFjKʵMr4pBˎcjZJC{(-VJ9'Vn*fo\(Š~Wϟu)=n\kjl0Em+ `R.n'd-A(giRxg8c.rayIP R?ZdH췥 (N¥/ڽf6H`QV {x5ZNf=悊 Ӊw}eqP']vXRBaGF{Cm WO)qMܓ |ݕDj @[- ؅R}˾~n8Ue8cm.Q0T w'\2HO.Tֶ=xzCM[/ <)PO̳\""Aa]ndI 7Y 8+,8r|{dy讣 2n}{ޟcՅ'oTY ,%I}-+QR9Y溿\5:df~5x#koZ}4%#~kNrޞ6F PP2daSg.i,<(}擑jUɕo74;C8XBNp qNZ֑@ekRHڕd+ۚ黜A+JZ2k6&i<,ʛ;wjQO=1ڰs (tFIP6޳hn*IE&q*V1y)JX?Bx{݄ꝀIO=%ڔǁ^#ycԇ2y{ӧ#%핊l[W בHִfi$RV9'յ$Ps߄*+,me.j7NT,5ܓ/c )FNBؖIܐqX H^VR;ҿ EDJSL9v䧋~ǜh4ҧ`WJs|[Vӎ>ʐeo(-Ђ;b葖P)D! G-YG;8Np$!){1KAN veX~ S!&C=5{߈!AIߋ%iwҒI}XL( r #$;=Ϫ|jPKy5_llBISs*>Ԅv7>〱nܒz Pb=8fuü=0T[M-tQ`s~BIu|xڝ>T^(]!Z:rw|3^%8>7jP!> tLh, kh* Ym-!ϒ9.vZ9rT:;+`0u7(9@ Bwn;z*&H#و889[NRṯ T-􄌂Pյ^m.`Bu%)q41'fX-Tiߔ.C') H/O㋾қQqHj)(a(i )9'OfZIIcLe&ȏ!?FB~;|pcF*B Rwq<MN8)[MV&❉Y6sI;6 ʈ9>`X+o)s =pxI8ҵPTVA r Qml3X.ud,J?FixZ׮-쒂 Y9Kq$%9X=I>HKuդPՓpeڷ)>bH`{%.4aS! +6SIN*Ij{ nV-S 5',d29QJ>JJi() ǜSݨT O1azR&`p*.I{Z=nmJ# prh})VSĝm$+rT)QN6Si.$*e*ڈOcD,G}" 0 wK%)7 txI'5N6KI8N%' jHߐ7 #)Rdf2w 3+JWJͷOҐ>pV95| !?I%x*Zp?,YТ㿽7TsFxBZGciHԧy *%ye1g1+!) yN$8 (erܓxg215z= 5`v^=K-uM;邓ҰPHBK 2Z Vҥ;Vɱ~&UN〜o2[u܇8Hjyu|e쓡 :xϊWM)p֦҉RRr9ɧTq@\+Zkqt&8;@wtWOg#;hҒ"K`;^mSgTy51-:-CqnViC-$zNi~Rm%iRJ][W8'KgrTd<@jQ))iCN)F@oێG$gxGdm^1Jn1Y y[ݱHn ÈhX6.snJ[c)bz %r)h#ӒN'ԣipcg%xKq{Ғ86ɘGrESJX&Jc^`ez풵[+f'ϊGH :YZ-mR_7fu'*qOޓkTxaIzg?mf>{q^6E=Qzi={O*~ʇ 6Sd,Uؔ%[Jpx+Dcr) /*>ԭARq4fq^NsS#{m)+@pcimr> X q ZH5(YceD #q*ZQH+#4orRH)ҟ~۔o6_Φ+NG(t_ K;sIGF1eB^OZJ1%:>Qy+ Zj6RZn-yRtin TbWw*Pzր0vR)=C8^fR4JR8SFy^6 "QV9ԳX1Dw#tȭni hj'<^j֠Ws^g/͖4sz֜a,)JRڀ ~'PK5P7djeQwX JT cUN#1 ܲPUnJTp9撍9d m$ x;rSݨ)]ԗE'ǽB԰6{z fԤpO{gl$rږt*ö+iAY8Lܻ =J9@0U9H8 SA?ûjGU榫9_ xO .IryRHZx#6kqKF֌Q2y䁜R3pk >֝ZU9.!4|' c8Jp+۵{chR[Em(\vb ì^f5#bGdZH10#diJZ>^^g풮+{%)@Bx`$q6PrNJǔ`qi.SQ06@n/'2GR87NB+<(񇌅cl_JBDvGz- EMu4m1KVǥQxYm 9-c sZYOrj51#-T{VQ@ C1nb+2Ax;eNңIh29?󅄄= 7Jj<d2m[|T5l kA})ɧSrv4d`Z• u9)33iv)x APRAj*Xp( $-̨[BAu[̀aky,%y߿ukW 뫴nbdIK>xR{$vT~GTEhد|;shKR`JRJ { 4MRH9u|@N#|۞ J ԋT!n @<< vNN#vG~Iـ}9\mิ d3Vl9Cd4UaI B{pXD nRI88h])۔1448|"x}х w'Jpdm=ҴG.:x{㝾8 ANvьI 㭦RT)McA9N5enmᕮC ;AaٓbrpKh!9wBֹԑ|);aMk/ 촸꒕`tZhiM{# 3S)X;dYO_bDr7r2; e֚/i;gv|7͸0Б%>Rs]R_}ix栏vK4ab7:6@KGX)7w!]!v3?n.(sOYU)Tz @RT+/0~е,59@!z6)c ㍾i2ٳh\wW)<)X8H:Z7c+7jYQBd=ni'(cnFPHZQJ%UQd#ԔPHڐ8$\3}DRQ/a,le-qIB)VXkRnڝ' 2$n*9IX”BMd\{$Z zxynڽk Q(5g ERT'GN㺄wQ4Q|+ixGˠ?ړsJD; daL%r0`CdAC%vBp%JSYd`HP"vF7VE+5) A 1[D#$6t,0j[>yԂpB[P䏷WNؓ<)嵢! njԿy+ʋWY1e mӴ Q͂VMvOqzk qA2X,k*Un}!{+v[:;iL-YG IR)Rq%ɛ$lqNDqa F8SS)kT8lMpK+$I`e2 L`=M<{5 \ dڐFFBqgi sjJBRZKiJUpM1,x:HL`t9uE\sc$)h^N186y RSG,׹<T'$;/]&J[dM{'|i/c٧A* ``ktP-'t+r[HPQM+]Γ8tbrnGjoj2nF-R8t†l@aWviVwMZA8[`g- rp;hi:=-S+TE>Mdq!,IJ07lyLlxH9(J~ , K )ŝqWt4%h<j'ܬic%,R@#{e]^i#L3%MT* Kp B4nļ$+sAg)Q=q8<&e8Ipolv*$9аOԤ cϊfӄMe@Bl6_vw}>*a->5 Mzvo/{m S P#ڰիӶVe[y%!+)[N;{bFFs"i.aY Jk#%Ot2{gxK1J:px BqŒkƷ<&o3i* R/RY^j)+R?|iFAV%<B6{׬i C;6e+9l{@AKQ Ȭc9~,Z!%JZY3kNSjFIиjpn2I`XHr4`4䕛 7v,t$g'^K'I%-0s_*kwku|-rN-ѓ0ا 7G%iVb.ePYAaQ  T=cKucMeԜn# h(QN,?Ggiޣd*R3bvy%+88t@22f)8}[NpVMiu5nnCiu'i\ӂC>$% 89^Vz{rSHB{ӐrS/$t4yMbLZ؝mN ?jO8rX]=QbbgX_PPK]4DYjKsNsۋal)@!Dl)m L{c<Ҭd֜d~—kJa-C~RA"qAI{sɴi) $7$$jVj4)uCIpN{j$"P)+npm!< gw%,`s◓Q+6ڤ-3ZSAdBS=n?Nei,!Za셥k*adAFz߽4*P+Iʭ}1x~ WIFī{v+j'QN|.z 3 1m <拋8H%_r9v sD@r~I  UIP.N5(u˽&(ԙDVG8P율s ~`Ҭv:Vnv}%Ld `5kS/۵b[%Zv#zIVldra4FI,ؽ$?>E4JmՏ5wZ !{O0;OK(h=ؘO q&KͲ |RG);X0RJIkqX۱Cp^ xOjT;s*X9Yn#y@>xĕt;n; $2KJqÓ^OW -l ;As>k7,Džx*ޔqӨ CLFh |RilhmCP>pH:1N8TV,xJLwlJ9jw5IܬCnT╘OeV'RNԎNj9:W`r^[F^/'#Vؔs\ q;&2ʛ m~0tY ( 8rh<-9Դr2pnR1*ӳJBIc#W:=:I$ v: s蘯u`()8ER9'gcQJნMNCs޽djģRvw\VF8MW(A^wqN.]yO^T#%K*KyaO㸃aVu_VH;e.+ZJj C%h[D¦mqSk'J!^@ǚx  a#Oul-z'dDvLSmʒG8 jXd:NR2jzݶH.+S6d Y㔛#Bԡ )@RQBP1ITUr- E12$ƴomI*}Q;)`$E j?V ޵)A#;j") ^ܫ#C'A9#H)Hi2i\KT۩X e'DTcu0%c*oo}Q7=)v!Yn}ZE nhei@7YpTM[2HPl ;L8 i}<`igR9N2- Ns&[ο0Im;q)oEAYFHN 'Qde ?Fg'')ڶ%fi엪ceԽ\KhNҁjf^s_sW8Mq܆‚8dZ)ې@+`x%A%ZhilU*C _*ݱ[NtBt6HM-/XgJP;,IؤPd҆ /pF+;a#p*wzf+rRA9ǺYl$];rK`c!*kDB@9K/W0h)v K1.qI>Ll2iIVs$t'ʈTiʒ!mE%KA V| +0<)[@QO,0RzOISihNUZC>$vS Nv+9R'xHMa۔{V,kGNwS%%jdTΕ @o%%hص!i\l,'&,wH f3RQrVT0dlt+7d2-O4s7N0VVqyݒScN`bh[A9 #V6Q`ai$$R&Wf\HHZie ؉w6K%_A^Թ+M~+C6NGyQj%nJ[JS*lj-( !S $H,e8s1FI'3Rv vN6Dmy -P4,"yLUz.!4$/'i5]!FC Y#GW9>8%hq~xM ՜cV1'uP˅@#`%%uj++FЯbi܌ m6V 3M-yov#y 8SvWhFsۿO[7+:2bX_\ 1[.焭v]՘)(V$}8꾏s5j )JTRc,HK6&(ܒ;aN#9Do[Pܮ*>f+)Ni G8N )͋R;8ngB t sĭh&NQn1 OuC,фqQ-pknnV agjѴ$VJ@x )N^Iko{b #4FcH^ ;$sM%rvئ@JqSVJtFTc^am@B3w#8O퀅>P8<,y†s,?nN6jp!Ӝr*X  owep#IfhlG>ZAE1RPU871TʢhHRֿQh bT; =ikw ZIx i9b!)F]F /z=ȍlG<jAy;&0NR'ENT-!DfٔVIl㱩+ةlKCpKYg8J{=J0@ όמtrJX'`RnGCNޒČ ވ޺qI]!8W^AsB0 JK=T̯{r\xl6M|dIjNn**nz-Uji T{O"hq$ZߵHiS`&!EU3On{J؀|LN&ukJmOç7HnZHqk u8&i_S-_xj:Vj~c2FFT,Nql[&҇rWBǞHB?3ETV%֐*Gr[sOŶ0dvH22^ra8=?Nn類a4$G:1v.+l.xmZ;r.m!#t]I @vԢ.XV1IOrRG~;T{#n4xxTYA픳]9?rwE>s{ÿڣhg,rHikW hrAE'VN0{SZzb[Kk##4nw \ әcL Ƣ lC X=;*d*3K(JI8rqⱦlӕW)>@qn;}U\0B՞ Hi +u5C*} Ő< iHaJZl>HT-t:pĸ&T>}CĦФnaYYBCA(eAU/1ڰ$eA%%3F<`-)\'ԯOs{}hch)l9NAô(X RJ|ޣj'1dc욤$:R0іH)gt Q󚅬-.%%22{UQ$! $FC9*`bv[ $`OX 9}PA 9` NO|?%,ٱ9qOmFSi:6?5-I;\7THlJZCIqcTΦlIVJ @_3mduڠR@l;-}9/aYʒfnzJ܉+ry۔1N@=\״NvH|wdpR#$>z~o.B4gQ'8$2u3u&C@RNHr a,vJ&\ $%$Vg~QQkvHYYg+R do$$fюRaY}dIHQkO+~@)ml>ՃsQд  WjSP# !A[Ў2Sd4FՂYiHX8{vR nJ/$á*H1qmd$'9gzdaRrv@n%ПZ!3HO) 8lSO~dw#_H ` L TQ%JQOqX+sؤ8%`qS#H8? m)RϪO85ozVB}i<9ÉH&.Uz]Xв~1搨a=RSS%H[< DFS{!jW'N< acI} Qr"]c8*JTA;?lg9Q{|}hI>Ʃ&G*n#u%mjO$(+[aRQR1%~u i}af 9^PS3[qŇR %G$"6J|+Vx改R!kf̐LՏl㚇ew \匫ze ޕ4zǒMG\!;OU?Ħp*,ZQi/9Ry*1e) hg*G|kVX.Mp%O)J'U呐T3lTIzHۊeP)%IS`QQPSwǵ-got1!ѕiJIeO]^ߕ"!p QQe:ISOvj=-8885 ppkMe $YSNa>By;qڣ猥~Fx5+H \qe%7mG~ B3 D\t Zp4Sal(y؞^anKq!!;Slx M5KmL9m=Af'^}kppsUjbgܪͅT".&N(6zpX5KpIwv$X!߯C8pHJqDUJ̿ Le!Gh=/)HL|Rr*}|~)(J KSp e){ry3NP';E2p#i8XBԐ;p4J-^a'TwRn?Oƕ$Q4PvKK)q0999V4V];cޚ=Qϝp) ##n=ӖERӅ RlG-Ic8KJ+)W}9ݒ,f8QFA+jI%IV !8b*f&WQuu)eo8`Nkk)TF2ɪ5LvTn@V5nzCh8<#ΜFN>D?Nܦ%EtzGy9=)%|sR2 ‹H#NI.aX@TPSd4< ʶBF0xvq QJECTRq :B 'v\OK Mܒh\HdrS^2рO m :Fw:b7rNgXlc+5<pǬ:2mI͸Ew+ktP :sA䯏]t麭%:Դi ҟ)ڻ3îF01oӁWfZ쩷AZR{&ݣJːLi $Vբ\t{N sɩHbv #t< 0x& MF6w)+`#Vmh&JII-yIs$EH6?;dnnW@^慰I 98 RRV) %#e015YԥWxR' `F{ט=mO .׿9Ni.mNy7||: (ԤY4S(ʎf%p %n qeĭ;TIdKH4N)Ro4˨3$r+J[ o J^ƣ>ҥ[[Xt. =Vʇ1pmTy43Üw?-SA9+HJR?֝(RKz÷89`(Z9s²N1IH.JiLk ^nKĀ昚x\ST@±RJIIpz81SIqv/nc?5tm-Z{JRL9`?H=P hSf;h(۹X)˙:7{kQ)Icyn4bod+ >*4& i8){vV8g8SOѣ 8!Ch"׫p"RC*>)NxN -hc4V;i\piaT]-)3M]IITՌCֶ7lVRjrٌMӲjy$C(%T{2r98Ze!@JPSǵR3ڟM$+pktg璠N5@WH'bZ`W-W2Փ-nC,B99.Y@nKIYP CdW7>Jw9)PXFwek$}%B>gw*MZQ\mšm3Rf`j:8RId%I=;' )>ݲ$g)N FqW8T4I' q\VHidӁ8Hm58ʹSpf˩!RZBy+MLR ",o)۽j{iӰR9;*n eT Fx;PCYpp4v`UVvY)H*Z܀t 8wVO} rY6sMF 79=&BHFѵRͫP5RR-^)e%fy]-:M:+- ` pe@r?мs-Rvt>#OozIsqJ+m2u(F7C' nT@٤2FcpUΫ[V)kf@ޕ~j"9oto !20S!/*PpB̕UaO z<Iq1Д@!#?bۥM;vV Z8 (-*lm튶P^Z)IjC-;OvE5a n**_$fY.BPjC+۴N~W͔RIxCYo3τ2 ǹ&b\=E`XَS-+4du;B#)IcS,9nJt2NrJ.Wd$ZAIS@I|bh=n Gir܅Z1tn?ImѬfT*9qL]V7s.q( FR95>B'tZS()yX)G%מDD'L'-š @Hz`F}[!)9"ȁY@GkRN;b<J5 *"H&9J:>p}< PR NJdӄ x(u;>z'brԥ# P$JvN̾qQP\ RqR5txy"R%)_ )3~̅QPXG #|齼*=&ɥN{ GϚP@7YCKɒ}2ӣ)6r[[NՅwfi$e;/R.z; F@P>_L#fg9;+B$C{)8S-N#|x$yǵ{Hv%?aE-ml%I$5U`d6ʛkN7Vp|S }D錱ﺖZF¥gsRZ2H1[!G9RV7 Q8*_ո)Z&lv-ziڂ'4t]4X&C;F+i+f6ټxQsÙv )& rvQÌ$H*9NC9xǷsNc-e%![sZ71&1GFl;$kILRB% rYʱv+)DUҠ{Mv uVzAQ! SYc;HunuI&\ŲҐ[RSɮ@ʤuX.eìmɕ9l $wA]8W`|6=*B#*QV{;mHsZ3qJqn-%>3Uޟ2n?k "Z\*;8IAQRFP\O޳bJWe(PQ $. rJ]$c^6c XBum+zJҭ`oRҀexK|zC`؀?:/p$wHpoA>ձXtF@?->JS^Cu߈ F(;$ChOSCٺTBs41QBYBW%0[B&0}T1XRm'#/d)kiB.my^SeS4#YdPq%Z#Wz:n?m ǵ:Sշ%0I%+#OnBdхhl4\+{~i=Ԩ['ÐyX35nlЬ52#)%be<ⷨ -%p$ⳒRU³mP*FHU'"]>aϥ1NZ8$ T=)qq+?Eѐl w':SgM !o]wEV|KUΉ_bڬ289iO*Jzm465_E^[ŒgV럭.+vH&hӲclU)t,Uv$yA,زuBV aXXkv[p-%ZeľDqcqQq8^UAVb@'k&V奩?Jnmڪ1Ip6>-u gԴ}9++eseVQ c>ki])eVa= VfVk[_ĕCR-Govr@$=* K+Z"#UxUTĨ:Tj {])V(ʡmQP$dԐze*f;m@tĠa;H4vqX?}𜥄 2(Ib^;j8o+ Լ? %phM(%99چn`HAQV .Viѷ- is% HJU_!ev* ؐH#@1c'xSw4 쨦ЗRtvTӃd *"u㟲YqP ݎi(ґɲ" RPy}%c&挗e3srvN' R2R{vYM̃aY--Rj@FKuF0U%2̀{)c):{` P5 HQ13ʯ]K9Dюa ʖEW򱏸VnnG:RJ))MGM'$,Se8i*+QC*Vr01')f nuMI۠s/iRalq p,#pRNaM#JlN=#P3C ^Pw3Byof6Ő uUj[ S8\Vem d:qʌ@d)\UY vRN!R{5-AR@̬!<(pEKƈ\ڛJR2y'4LW) +u )VQ䠨4S0 Fri!f# OƘBӕ8P,R LR੕𔧑jt%M|FyL8_#):srZ{%GqL$HB$e_Y`"TՄ  N^‰=k';ʗV)(VG>ƙԹ0RɒN43P7Q=c /0W8#rT65l[nr/^<.85WUtOI-R$( [.N㎳kC 5 9 s[@sBHUVôpjɯHL&;-~׀bBFg8`l9B8u2+/4;iy>vR 9)SQøQ8MdK0N{Qo3ޔxh҃ml1!c E,1\Vl1R&5]4\>1ڽDlm )_7l^e*Jҁ*59^i /P$K ]Xexjp׏1Ȥե/tKN:`ї$wKe)N)H򗉄rq}3ڼ  (N2tԌҍYT YJDxlidx'n6`).#@9M삙UBF@YښERH;T ?QcH tJ)e3[ũYU,#XVG4ݠSӳ+PJ9htu(k#AO>kQߓ@4(FZVA9hI/8)`jc)|8` )FW%,Sݽ!YOԔo*CŨ$u窓eR) dn$㊎ a7XH!fBPRuCppN>F~vJ[Cm R#;΅YCA***qH2FG,pNWAN\D a PST8Wh^tdJey'ux '3(QYqkjNpp[+hҜ@pJz?Tt"0^uIJTFʁ&' #aePv283%e"vI|c ֭<;' nN@&dDm/8%6{V@zJ+}ZZڲ @|Q\ϩ\_7y E N8Kl-J5%dT,oeN0kyNj<[\ܞ|W,vG*Q\Qy币wƵ;(N j"S ;+%iǭQA)% }SUDug[$[88LQLUm6 #;!ri]h{7AT@aW"V*xU!&S.z@BJ%I-n[>՛Z2*WϚ ZN(LSpNy80jq'!+^i( (ָ$!\s-ϚkFR1(2=F7>)8Q?P )hxVQC%+&PwyW'+·63MDm/ p\_}|mlm-IDN+3櫳 򗗅+aŐya92j}Mܯd}g)u+Q|Px6`xj# ƂA') m):)$[~mZcxoIָHNbJ-/T}ql\X@jbN2Tޥa\\:85 N cjDRQ"e 8Zqh) V?j_Z>`)KO8J22{@OQ^p8+(Gj$JvyQk "9j:psmk֢y>3Qn&֠p{i Wa╨h;4-j62aJRTⓢqR4a+ܤ5R7$dnZq99p+CHXT0_-)gqڳڭ7{U}[Q\V[_Ԃ+!7e/?.(\xpx|=`,nW V`\^pҠr\^IϚCxTǝKHCY$r ݴ@=mIFLprBWA YY${%Cf GSƝԠLjZ%IqGU ;9KңvR?/7^TOp)jSdC3,[pJz&juTiQn`*PQejf[@ 7$juu, tI#SXKWO?w)HR)%VIHH=+ќRQL$yՄݓs5|&j>ȅyIk$GwBcpp-netlib-0.11.2-final/libs/network/doc/_static/pygments.css000066400000000000000000000067061256751517300241410ustar00rootroot00000000000000.hll { background-color: #404040 } .c { color: #999999; font-style: italic } /* Comment */ .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .g { color: #d0d0d0 } /* Generic */ .k { color: #6ab825; font-weight: bold } /* Keyword */ .l { color: #d0d0d0 } /* Literal */ .n { color: #d0d0d0 } /* Name */ .o { color: #d0d0d0 } /* Operator */ .x { color: #d0d0d0 } /* Other */ .p { color: #d0d0d0 } /* Punctuation */ .cm { color: #999999; font-style: italic } /* Comment.Multiline */ .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */ .c1 { color: #999999; font-style: italic } /* Comment.Single */ .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ .gd { color: #d22323 } /* Generic.Deleted */ .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ .gr { color: #d22323 } /* Generic.Error */ .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ .gi { color: #589819 } /* Generic.Inserted */ .go { color: #cccccc } /* Generic.Output */ .gp { color: #aaaaaa } /* Generic.Prompt */ .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ .gt { color: #d22323 } /* Generic.Traceback */ .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */ .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */ .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */ .kp { color: #6ab825 } /* Keyword.Pseudo */ .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */ .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */ .ld { color: #d0d0d0 } /* Literal.Date */ .m { color: #3677a9 } /* Literal.Number */ .s { color: #ed9d13 } /* Literal.String */ .na { color: #bbbbbb } /* Name.Attribute */ .nb { color: #24909d } /* Name.Builtin */ .nc { color: #447fcf; text-decoration: underline } /* Name.Class */ .no { color: #6AB825 } /* Name.Constant */ .nd { color: #ffa500 } /* Name.Decorator */ .ni { color: #d0d0d0 } /* Name.Entity */ .ne { color: #bbbbbb } /* Name.Exception */ .nf { color: #447fcf } /* Name.Function */ .nl { color: #d0d0d0 } /* Name.Label */ .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */ .nx { color: #d0d0d0 } /* Name.Other */ .py { color: #d0d0d0 } /* Name.Property */ .nt { color: #6ab825; font-weight: bold } /* Name.Tag */ .nv { color: #40ffff } /* Name.Variable */ .ow { color: #6ab825; font-weight: bold } /* Operator.Word */ .w { color: #666666 } /* Text.Whitespace */ .mf { color: #3677a9 } /* Literal.Number.Float */ .mh { color: #3677a9 } /* Literal.Number.Hex */ .mi { color: #3677a9 } /* Literal.Number.Integer */ .mo { color: #3677a9 } /* Literal.Number.Oct */ .sb { color: #ed9d13 } /* Literal.String.Backtick */ .sc { color: #ed9d13 } /* Literal.String.Char */ .sd { color: #ed9d13 } /* Literal.String.Doc */ .s2 { color: #ed9d13 } /* Literal.String.Double */ .se { color: #ed9d13 } /* Literal.String.Escape */ .sh { color: #ed9d13 } /* Literal.String.Heredoc */ .si { color: #ed9d13 } /* Literal.String.Interpol */ .sx { color: #ffa500 } /* Literal.String.Other */ .sr { color: #ed9d13 } /* Literal.String.Regex */ .s1 { color: #ed9d13 } /* Literal.String.Single */ .ss { color: #ed9d13 } /* Literal.String.Symbol */ .bp { color: #24909d } /* Name.Builtin.Pseudo */ .vc { color: #40ffff } /* Name.Variable.Class */ .vg { color: #40ffff } /* Name.Variable.Global */ .vi { color: #40ffff } /* Name.Variable.Instance */ .il { color: #3677a9 } /* Literal.Number.Integer.Long */ cpp-netlib-0.11.2-final/libs/network/doc/_static/reset-fonts-grids.css000066400000000000000000000126221256751517300256440ustar00rootroot00000000000000/* Copyright (c) 2008, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.5.1 */ html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;font-variant:normal;}sup {vertical-align:text-top;}sub {vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}body {font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;} body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}s .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}cpp-netlib-0.11.2-final/libs/network/doc/_static/uri.svg000066400000000000000000000721231256751517300230750ustar00rootroot00000000000000 image/svg+xml mailto:john.doe@example.com { scheme { path ftp://john.doe:password@www.example.com:8021 { scheme { host { port password { { username { user_info { authority http://www.example.com/resource/?key=value#page1 { scheme path { { authority { query { fragment cpp-netlib-0.11.2-final/libs/network/doc/conf.py000066400000000000000000000102431256751517300214210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # cpp-netlib documentation build configuration file, created by # sphinx-quickstart on Wed Jun 23 20:50:04 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.append(os.path.abspath('_ext')) # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.todo', 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.coverage', ] todo_include_todos = True # Add any paths that contain templates here, relative to this directory. # templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. source_encoding = 'utf-8' # The master toctree document. master_doc = 'contents' # General information about the project. project = u'cpp-netlib' copyright = u'2008-2014, Glyn Matthews, Dean Michael Berris; 2013 Google, Inc.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.11' # The full version, including alpha/beta/rc tags. release = '0.11.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. unused_docs = [ '' ] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['build', 'doxyxml', 'ext'] # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. # pygments_style = 'sphinx' pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'pyramid' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'cpp-netlib v0.11.2' # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = 'cpp-netlib' # Use an HTML index. html_use_index = False # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_style = 'cpp-netlib.css' # html_static_path = ['_static'] # html_translator_class = "adjusts.CppNetlibHTMLTranslator" # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. html_use_smartypants = True # Output file base name for HTML help builder. # htmlhelp_basename = 'cpp-netlibdoc' cpp-netlib-0.11.2-final/libs/network/doc/contents.rst000066400000000000000000000003311256751517300225060ustar00rootroot00000000000000.. _contents: Contents -------- .. toctree:: :maxdepth: 4 index.rst whats_new.rst getting_started.rst examples.rst in_depth.rst techniques.rst history.rst reference.rst references.rst cpp-netlib-0.11.2-final/libs/network/doc/examples.rst000066400000000000000000000014421256751517300224730ustar00rootroot00000000000000.. _examples: Examples ======== The :mod:`cpp-netlib` is a practical library that is designed to aid the development of applications for that need to communicate using common networking protocols. The following set of examples describe a series of realistic examples that use the :mod:`cpp-netlib` for these kinds of application. All examples are built using CMake. HTTP examples ````````````` The HTTP component of the :mod:`cpp-netlib` contains a client and server. The examples that follow show how to use both for programs that can be embedded into larger applications. .. toctree:: :maxdepth: 1 examples/http/http_client examples/http/simple_wget examples/http/hello_world_server examples/http/hello_world_client examples/http/atom_reader examples/http/twitter_search cpp-netlib-0.11.2-final/libs/network/doc/examples/000077500000000000000000000000001256751517300217405ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/examples/http/000077500000000000000000000000001256751517300227175ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/examples/http/atom_reader.rst000066400000000000000000000041671256751517300257430ustar00rootroot00000000000000.. _atom_reader: ****************** Atom feed reader ****************** The next examples show some simple, more practical applications using the HTTP client. The first one reads a simple Atom_ feed and prints the titles of each entry to the console. .. _Atom: http://en.wikipedia.org/wiki/Atom_(standard) The code ======== .. code-block:: c++ #include "atom.hpp" #include #include #include int main(int argc, char * argv[]) { using namespace boost::network; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } try { http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); atom::feed feed(response); std::cout << "Feed: " << feed.title() << " (" << feed.subtitle() << ")" << std::endl; BOOST_FOREACH(const atom::entry &entry, feed) { std::cout << entry.title() << " (" << entry.published() << ")" << std::endl; } } catch (std::exception &e) { std::cerr << e.what() << std::endl; } return 0; } Building and running ``atom_reader`` ==================================== .. code-block:: bash $ cd ~/cpp-netlib-build $ make atom_reader And to run the example from the command line to access the feed that lists of all the commits on cpp-netlib's master branch: .. code-block:: bash $ ./example/atom_reader https://github.com/cpp-netlib/cpp-netlib/commits/master.atom Diving into the code ==================== Most of this will now be familiar. The response is passed to the constructor to the ``atom::feed`` class, which parses the resultant XML. To keep this example as simple as possible, `rapidxml`_, a header-only XML parser library, was used to parse the response. .. _`rapidxml`: http://rapidxml.sourceforge.net/ A similar example using RSS feeds exists in ``libs/network/example/rss``. cpp-netlib-0.11.2-final/libs/network/doc/examples/http/hello_world_client.rst000066400000000000000000000053241256751517300273250ustar00rootroot00000000000000.. _hello_world_http_client: *************************** "Hello world" HTTP client *************************** Since we have a "Hello World" HTTP server, let's then create an HTTP client to access that server. This client will be similar to the HTTP client we made earlier in the documentation. The code ======== We want to create a simple HTTP client that just makes a request to the HTTP server that we created earlier. This really simple client will look like this: .. code-block:: c++ #include #include #include #include namespace http = boost::network::http; int main(int argc, char * argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; } try { http::client client; std::ostringstream url; url << "http://" << argv[1] << ":" << argv[2] << "/"; http::client::request request(url.str()); http::client::response response = client.get(request); std::cout << body(response) << std::endl; } catch (std::exception & e) { std::cerr << e.what() << std::endl; return 1; } return 0; } Building and running the client =============================== Just like with the HTTP Server and HTTP client example before, we can build this example by doing the following on the shell: .. code-block:: bash $ cd ~/cpp-netlib-build $ make hello_world_client This example can be run from the command line as follows: .. code-block:: bash $ ./example/hello_world_client http://127.0.0.1:8000 .. note:: This assumes that you have the ``hello_world_server`` running on localhost port 8000. Diving into the code ==================== All this example shows is how easy it is to write an HTTP client that connects to an HTTP server, and gets the body of the response. The relevant lines are: .. code-block:: c++ http::client client; http::client::request request(url.str()); http::client::response response = client.get(request); std::cout << body(response) << std::endl; You can then imagine using this in an XML-RPC client, where you can craft the XML-RPC request as payload which you can pass as the body to a request, then perform the request via HTTP: .. code-block:: c++ http::client client; http::client::request request("http://my.webservice.com/"); http::client::response = client.post(request, some_xml_string, "application/xml"); std::data = body(response); The next set of examples show some more practical applications using the :mod:`cpp-netlib` HTTP client. cpp-netlib-0.11.2-final/libs/network/doc/examples/http/hello_world_server.rst000066400000000000000000000103251256751517300273520ustar00rootroot00000000000000.. _hello_world_http_server: *************************** "Hello world" HTTP server *************************** Now that we've seen how we can deal with request and response objects from the client side, we'll see how we can then use the same abstractions on the server side. In this example we're going to create a simple HTTP Server in C++ using :mod:`cpp-netlib`. The code ======== The :mod:`cpp-netlib` provides the framework to develop embedded HTTP servers. For this example, the server is configured to return a simple response to any HTTP request. .. code-block:: c++ #include #include #include namespace http = boost::network::http; struct hello_world; typedef http::server server; struct hello_world { void operator() (server::request const &request, server::response &response) { std::string ip = source(request); response = server::response::stock_reply( server::response::ok, std::string("Hello, ") + ip + "!"); } }; int main(int argc, char * argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; } try { hello_world handler; server server_(argv[1], argv[2], handler); server_.run(); } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } This is about a straightforward as server programming will get in C++. Building and running the server =============================== Just like with the HTTP client, we can build this example by doing the following on the shell: .. code-block:: bash $ cd ~/cpp-netlib-build $ make hello_world_server The first two arguments to the ``server`` constructor are the host and the port on which the server will listen. The third argument is the the handler object defined previously. This example can be run from a command line as follows: .. code-block:: bash $ ./example/hello_world_server 0.0.0.0 8000 .. note:: If you're going to run the server on port 80, you may have to run it as an administrator. Diving into the code ==================== Let's take a look at the code listing above in greater detail. .. code-block:: c++ #include This header contains all the code needed to develop an HTTP server with :mod:`cpp-netlib`. .. code-block:: c++ struct hello_world; typedef http::server server; struct hello_world { void operator () (server::request const &request, server::response &response) { std::string ip = source(request); response = server::response::stock_reply( server::response::ok, std::string("Hello, ") + ip + "!"); } }; ``hello_world`` is a functor class which handles HTTP requests. All the operator does here is return an HTTP response with HTTP code 200 and the body ``"Hello, !"``. The ```` in this case would be the IP address of the client that made the request. There are a number of pre-defined stock replies differentiated by status code with configurable bodies. All the supported enumeration values for the response status codes can be found in ``boost/network/protocol/http/impl/response.ipp``. .. code-block:: c++ hello_world handler; server server_(argv[1], argv[2], handler); server_.run(); The first two arguments to the ``server`` constructor are the host and the port on which the server will listen. The third argument is the the handler object defined previously. .. note:: In this example, the server is specifically made to be single-threaded. In a multi-threaded server, you would invoke the ``hello_world::run`` member method in a set of threads. In a multi-threaded environment you would also make sure that the handler does all the necessary synchronization for shared resources across threads. The handler is passed by reference to the server constructor and you should ensure that any calls to the ``operator()`` overload are thread-safe. cpp-netlib-0.11.2-final/libs/network/doc/examples/http/http_client.rst000066400000000000000000000066251256751517300257770ustar00rootroot00000000000000.. _http_client: ************* HTTP client ************* The first code example is the simplest thing you can do with the :mod:`cpp-netlib`. The application is a simple HTTP client, which can be found in the subdirectory ``libs/network/example/http_client.cpp``. All this example doing is creating and sending an HTTP request to a server and printing the response body. The code ======== Without further ado, the code to do this is as follows: .. code-block:: c++ #include #include int main(int argc, char *argv[]) { using namespace boost::network; if (argc != 2) { std::cout << "Usage: " << argv[0] << " [url]" << std::endl; return 1; } http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; return 0; } Running the example =================== You can then run this to get the Boost_ website: .. code-block:: bash $ cd ~/cpp-netlib-build $ make http_client $ ./example/http_client http://www.boost.org/ .. _Boost: http://www.boost.org/ .. note:: The instructions for all these examples assume that :mod:`cpp-netlib` is build outside the source tree, according to `CMake conventions`_. For the sake of consistency we assume that this is in the ``~/cpp-netlib-build`` directory. .. _`CMake conventions`: http://www.cmake.org/Wiki/CMake_FAQ#What_is_an_.22out-of-source.22_build.3F Diving into the code ==================== Since this is the first example, each line will be presented and explained in detail. .. code-block:: c++ #include All the code needed for the HTTP client resides in this header. .. code-block:: c++ http::client client; First we create a ``client`` object. The ``client`` abstracts all the connection and protocol logic. The default HTTP client is version 1.1, as specified in `RFC 2616`_. .. code-block:: c++ http::client::request request(argv[1]); Next, we create a ``request`` object, with a URI string passed as a constructor argument. .. code-block:: c++ request << header("Connection", "close"); :mod:`cpp-netlib` makes use of stream syntax and *directives* to allow developers to build complex message structures with greater flexibility and clarity. Here, we add the HTTP header "Connection: close" to the request in order to signal that the connection will be closed after the request has completed. .. code-block:: c++ http::client::response response = client.get(request); Once we've built the request, we then make an HTTP GET request throught the ``http::client`` from which an ``http::response`` is returned. ``http::client`` supports all common HTTP methods: GET, POST, HEAD, DELETE. .. code-block:: c++ std::cout << body(response) << std::endl; Finally, though we don't do any error checking, the response body is printed to the console using the ``body`` directive. That's all there is to the HTTP client. In fact, it's possible to compress this to a single line: .. code-block:: c++ std::cout << body(http::client().get(http::request("http://www.boost.org/"))); The next example will introduce the ``uri`` class. .. _`RFC 2616`: http://www.w3.org/Protocols/rfc2616/rfc2616.html cpp-netlib-0.11.2-final/libs/network/doc/examples/http/simple_wget.rst000066400000000000000000000060541256751517300257750ustar00rootroot00000000000000.. _simple_wget: *************** Simple `wget` *************** This example is a very simple implementation of a ``wget`` style clone. It's very similar to the previous example, but introduces the ``uri`` class. The code ======== .. code-block:: c++ #include #include #include #include #include namespace http = boost::network::http; namespace uri = boost::network::uri; namespace { std::string get_filename(const uri::uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); return filename.empty()? "index.html" : filename; } } // namespace int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " url" << std::endl; return 1; } try { http::client client; http::client::request request(argv[1]); http::client::response response = client.get(request); std::string filename = get_filename(request.uri()); std::cout << "Saving to: " << filename << std::endl; std::ofstream ofs(filename.c_str()); ofs << static_cast(body(response)) << std::endl; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } Running the example =================== You can then run this to copy the Boost_ website: .. code-block:: bash $ cd ~/cpp-netlib-build $ make simple_wget $ ./example/simple_wget http://www.boost.org/ $ cat index.html .. _Boost: http://www.boost.org/ Diving into the code ==================== As with ``wget``, this example simply makes an HTTP request to the specified resource, and saves it on the filesystem. If the file name is not specified, it names the resultant file as ``index.html``. The new thing to note here is use of the ``uri`` class. The ``uri`` takes a string as a constructor argument and parses it. The ``uri`` parser is fully-compliant with `RFC 3986`_. The URI is provided in the following header: .. _`RFC 3986`: http://www.ietf.org/rfc/rfc3986.txt .. code-block:: c++ #include Most of the rest of the code is familiar from the previous example. To retrieve the URI resource's file name, the following function is provided: .. code-block:: c++ std::string get_filename(const uri::uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); return filename.empty()? "index.html" : filename; } The ``uri`` interface provides access to its different components: ``scheme``, ``user_info``, ``host``, ``port``, ``path``, ``query`` and ``fragment``. The code above takes the URI path to determine the resource name. Next we'll develop a simple client/server application using ``http::server`` and ``http::client``. cpp-netlib-0.11.2-final/libs/network/doc/examples/http/twitter_search.rst000066400000000000000000000066061256751517300265100ustar00rootroot00000000000000.. _twitter_search: **************** Twitter search **************** This example uses `Twitter's search API`_ to list recent tweets given a user query. New features introduced here include the URI builder and ``uri::encoded`` function. .. _`Twitter's search API`: https://dev.twitter.com/docs/using-search The code ======== .. code-block:: c++ #include #include "rapidjson/rapidjson.h" #include "rapidjson/document.h" #include int main(int argc, char *argv[]) { using namespace boost::network; using namespace rapidjson; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } try { http::client client; uri::uri base_uri("http://search.twitter.com/search.json"); std::cout << "Searching Twitter for query: " << argv[1] << std::endl; uri::uri search; search << base_uri << uri::query("q", uri::encoded(argv[1])); http::client::request request(search); http::client::response response = client.get(request); Document d; if (!d.Parse<0>(response.body().c_str()).HasParseError()) { const Value &results = d["results"]; for (SizeType i = 0; i < results.Size(); ++i) { const Value &user = results[i]["from_user_name"]; const Value &text = results[i]["text"]; std::cout << "From: " << user.GetString() << std::endl << " " << text.GetString() << std::endl << std::endl; } } } catch (std::exception &e) { std::cerr << e.what() << std::endl; } return 0; } .. note:: To parse the results of these queries, this example uses `rapidjson`_, a header-only library that is released under the `MIT License`_. .. _`rapidjson`: http://code.google.com/p/rapidjson/ .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php Building and running ``twitter_search`` ======================================= .. code-block:: bash $ cd ~/cpp-netlib-build $ make twitter_search Twitter provides a powerful set of operators to modify the behaviour of search queries. Some examples are provided below: .. code-block:: bash $ ./example/twitter_search "Lady Gaga" Returns any results that contain the exact phrase "Lady Gaga". .. code-block:: bash $ ./example/twitter_search "#olympics" Returns any results with the #olympics hash tag. .. code-block:: bash $ ./example/twitter_search "flight :(" Returns any results that contain "flight" and have a negative attitude. More examples can be found on `Twitter's search API`_ page. Diving into the code ==================== .. code-block:: c++ uri::uri base_uri("http://search.twitter.com/search.json"); std::cout << "Searching Twitter for query: " << argv[1] << std::endl; uri::uri search; search << base_uri << uri::query("q", uri::encoded(argv[1])); The :mod:`cpp-netlib` URI builder uses a stream-like syntax to allow developers to construct more complex URIs. The example above re-uses the same base URI and allows the command line argument to be used as part of the URI query. The builder also supports percent encoding using the ``encoded`` directive. cpp-netlib-0.11.2-final/libs/network/doc/getting_started.rst000066400000000000000000000235521256751517300240520ustar00rootroot00000000000000.. _getting_started: ***************** Getting Started ***************** Downloading an official release =============================== You can find links to the latest official release from the project's official website: http://cpp-netlib.org/ All previous stable versions of :mod:`cpp-netlib` can be downloaded from Github_ from this url: http://github.com/cpp-netlib/cpp-netlib/downloads Each release is available as gzipped (Using the command ``tar xzf cpp-netlib.tar.gz``) or bzipped (Using ``tar xjf cpp-netlib.tar.bz2``) tarball, or as a zipfile (``unzip cpp-netlib.zip``, or on Windows using a tool such as 7zip_). .. _Github: http://github.com/cpp-netlib/cpp-netlib/downloads .. _7zip: http://www.7-zip.org/ Downloading a development version ================================= The :mod:`cpp-netlib` uses Git_ for source control, so to use any development versions Git must be installed on your system. Using the command line, the command to get the latest code is: :: shell$ git clone git://github.com/cpp-netlib/cpp-netlib.git This should be enough information get to started. To do more complex things with Git, such as pulling changes or checking out a new branch, refer to the `Git documentation`_. .. note:: Previous versions of :mod:`cpp-netlib` referred to the *mikhailberis* repository as the main development repository. This account is still valid, but not always up-to-date. In the interest of consistency, the main repository has been changed to *cpp-netlib*. Windows users need to use msysGit_, and to invoke the command above from a shell. For fans of Subversion_, the same code can be checked out from http://svn.github.com/cpp-netlib/cpp-netlib.git. .. _Git: http://git-scm.com/ .. _`Git documentation`: http://git-scm.com/documentation .. _msysGit: http://code.google.com/p/msysgit/downloads/list .. _Subversion: http://subversion.tigris.org/ .. note:: The :mod:`cpp-netlib` project is hosted on GitHub_ and follows the prescribed development model for GitHub_ based projects. This means in case you want to submit patches, you will have to create a fork of the project (read up on forking_) and then submit a pull request (read up on submitting `pull requests`_). .. _forking: http://help.github.com/forking/ .. _`pull requests`: http://help.github.com/pull-requests/ Getting Boost ============= :mod:`cpp-netlib` depends on Boost_. It should work for any version of Boost above 1.50.0. If Boost is not installed on your system, the latest package can be found on the `Boost web-site`_. The environment variable ``BOOST_ROOT`` must be defined, which must be the full path name of the top directory of the Boost distribution. Although Boost is mostly header only, applications built using :mod:`cpp-netlib` still requires linking with `Boost.System`_, `Boost.Date_time`_, and `Boost.Regex`_. .. _Boost: http://www.boost.org/doc/libs/release/more/getting_started/index.html .. _`Boost web-site`: http://www.boost.org/users/download/ .. _`Boost.System`: http://www.boost.org/libs/system/index.html .. _`Boost.Date_time`: http://www.boost.org/libs/date_time/index.html .. _`Boost.Regex`: http://www.boost.org/libs/regex/index.html .. note:: You can follow the steps in the `Boost Getting Started`_ guide to install Boost into your development system. .. _`Boost Getting Started`: http://www.boost.org/doc/libs/release/more/getting_started/index.html .. warning:: There is a known incompatibility between :mod:`cpp-netlib` and Boost 1.46.1 on some compilers. It is not recommended to use :mod:`cpp-netlib` with Boost 1.46.1. Some have reported though that Boost 1.47.0 and :mod:`cpp-netlib` work together better. Getting CMake ============= The :mod:`cpp-netlib` uses CMake_ to generate platform-specific build files. If you intend to run the test suite, you can follow the instructions below. Otherwise, you don't need CMake to use :mod:`cpp-netlib` in your project. The :mod:`cpp-netlib` requires CMake version 2.8 or higher. .. _CMake: http://www.cmake.org/ Let's assume that you have unpacked the :mod:`cpp-netlib` at the top of your HOME directory. On Unix-like systems you will typically be able to change into your HOME directory using the command ``cd ~``. This sample below assumes that the ``~/cpp-netlib`` directory exists, and is the top-level directory of the :mod:`cpp-netlib` release. Building with CMake =================== To build the tests that come with :mod:`cpp-netlib`, we first need to configure the build system to use our compiler of choice. This is done by running the ``cmake`` command at the top-level directory of :mod:`cpp-netlib` with additional parameters:: $ mkdir ~/cpp-netlib-build $ cd ~/cpp-netlib-build $ cmake -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=gcc \ > -DCMAKE_CXX_COMPILER=g++ \ > ../cpp-netlib .. note:: While it's not compulsory, it's recommended that :mod:`cpp-netlib` is built outside the source directory. For the purposes of documentation, we'll assume that all builds are done in ``~/cpp-netlib-build``. If you intend to use the SSL support when using the HTTP client libraries in :mod:`cpp-netlib`, you may need to build it with OpenSSL_ installed or at least available to CMake. If you have the development headers for OpenSSL_ installed on your system when you build :mod:`cpp-netlib`, CMake will be able to detect it and set the ``BOOST_NETWORK_ENABLE_HTTPS`` macro when building the library to support HTTPS URIs. One example for building the library with OpenSSL_ support with a custom (non-installed) version of OpenSSL_ is by doing the following:: $ cmake -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=clang \ > -DCMAKE_CXX_COMPILER=clang++ \ > -DOPENSSL_ROOT_DIR=/Users/dberris/homebrew/Cellar/openssl/1.0.1f > ../cpp-netlib .. _OpenSSL: http://www.openssl.org/ You can also use a different root directory for the Boost_ project by using the ``-DBOOST_ROOT`` configuration option to CMake. This is useful if you intend to build the library with a specific version of Boost that you've built in a separate directory:: $ cmake -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=clang \ > -DCMAKE_CXX_COMPILER=clang++ \ > -DOPENSSL_ROOT_DIR=/Users/dberris/homebrew/Cellar/openssl/1.0.1f \ > -DBOOST_ROOT=/Users/dberris/Source/boost_1_55_0 > ../cpp-netlib Building on Linux ~~~~~~~~~~~~~~~~~ On Linux, this will generate the appropriate Makefiles that will enable you to build and run the tests and examples that come with :mod:`cpp-netlib`. To build the tests, you can run ``make`` in the same top-level directory of ``~/cpp-netlib-build``:: $ make .. note:: Just like with traditional GNU Make, you can add the ``-j`` parameter to specify how many parallel builds to run. In case you're in a sufficiently powerful system and would like to parallelize the build into 4 jobs, you can do this with:: make -j4 As a caveat, :mod:`cpp-netlib` is heavy on template metaprogramming and will require a lot of computing and memory resources to build the individual tests. Do this at the risk of thrashing_ your system. However, this compile-time burden is much reduced in recent versions. .. _thrashing: http://en.wikipedia.org/wiki/Thrashing_(computer_science) Once the build has completed, you can now run the test suite by issuing:: $ make test You can install :mod:`cpp-netlib` by issuing:: $ sudo make install By default this installs :mod:`cpp-netlib` into ``/usr/local``. .. note:: As of version 0.9.3, :mod:`cpp-netlib` produces three static libraries. Using GCC on Linux these are:: libcppnetlib-client-connections.a libcppnetlib-server-parsers.a libcppnetlib-uri.a Users can find them in ``~/cpp-netlib-build/libs/network/src``. Building On Windows ~~~~~~~~~~~~~~~~~~~ If you're using the Microsoft Visual C++ compiler or the Microsoft Visual Studio IDE and you would like to build :mod:`cpp-netlib` from within Visual Studio, you can look for the solution and project files as the artifacts of the call to ``cmake`` -- the file should be named ``CPP-NETLIB.sln`` (the solution) along with a number of project files for Visual Studio. .. note:: As of version 0.9.3, :mod:`cpp-netlib` produces three static libraries. Using Visual C++ on Windows they are:: cppnetlib-client-connections.lib cppnetlib-server-parsers.lib cppnetlib-uri.lib Users can find them in ``~/cpp-netlib-build/libs/network/src``. Using :mod:`cpp-netlib` ======================= CMake projects ~~~~~~~~~~~~~~ Projects using CMake can add the following lines in their ``CMakeLists.txt`` to be able to use :mod:`cpp-netlib`:: set ( CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ~/cpp-netlib-build ) find_package ( cppnetlib 0.11.0 REQUIRED ) include_directories ( ${CPPNETLIB_INCLUDE_DIRS} ) target_link_libraries ( MyApplication ${CPPNETLIB_LIBRARIES} ) .. note:: Setting ``CMAKE_PREFIX_PATH`` is only required when :mod:`cpp-netlib` is not installed to a location that CMake searches. When :mod:`cpp-netlib` is installed to the default location (``/usr/local``), ``CMake`` can find it. .. note:: We assume that ``MyApplication`` is the application that you are building and which depends on :mod:`cpp-netlib`. Reporting Issues, Getting Support ================================= In case you find yourself stuck or if you've found a bug (or you want to just join the discussion) you have a few options to choose from. For reporting bugs, feature requests, and asking questions about the implementation and/or the documentation, you can go to the GitHub issues page for the project at http://github.com/cpp-netlib/cpp-netlib/issues. You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list through http://groups.google.com/forum/#!forum/cpp-netlib. cpp-netlib-0.11.2-final/libs/network/doc/history.rst000066400000000000000000000041711256751517300223600ustar00rootroot00000000000000Project history =============== The :mod:`cpp-netlib` was founded by Dean Michael Berris in 2007. Initially it consisted of a message template and an HTTP client. It found a home on Sourceforge_ but was migrated at the end of 2009 to Github_ where development is actively continued by a committed community. Motivation ~~~~~~~~~~ We're a group of C++ developers and we kept becoming annoyed that we had to repeatedly write the same code when building applications that needed to be network-aware. We found that there was a lack of accessible networking libraries, either standard or open source, that fulfilled our needs. Such libraries exist for every other major language. So, building on top of `Boost.Asio`_, we decided to get together and build our own. Objectives ~~~~~~~~~~ The objectives of the :mod:`cpp-netlib` are to: * develop a high quality, portable, easy to use C++ networking library * enable developers to easily extend the library * lower the barrier to entry for cross-platform network-aware C++ applications The goal the of :mod:`cpp-netlib` has never been to build a fully-featured web server - there are plenty of excellent options already available. The niche that this library targets is for light-weight networking functionality for C++ applications that have demanding performance requirements or memory constraints, but that also need to be portable. This type of application is becoming increasingly common as software becomes more distributed, and applications need to communicate with services. While many languages provide direct library support for high level network programming, this feature is missing in C++. Therefore, this library has been developed with the intention of eventually being submitted to Boost_, a collection of general, high quality libraries for C++ developers. Eventually, the :mod:`cpp-netlib` will be extended to support many of the application layer protocols such as SMTP, FTP, SOAP, XMPP etc. .. _Sourceforge: http://sourceforge.net/projects/cpp-netlib/ .. _Github: http://github.com/cpp-netlib/cpp-netlib .. _Boost: http://www.boost.org/ .. _`Boost.Asio`: http://www.boost.org/libs/asio/ cpp-netlib-0.11.2-final/libs/network/doc/in_depth.rst000066400000000000000000000005331256751517300224470ustar00rootroot00000000000000.. _in_depth: An in-depth look at the :mod:`cpp-netlib` ========================================= The :mod:`cpp-netlib` is composed of three different sets of functionality: a **message** template, a **URI** template and different **protocol** implementations. .. toctree:: :maxdepth: 2 in_depth/message in_depth/uri in_depth/http cpp-netlib-0.11.2-final/libs/network/doc/in_depth/000077500000000000000000000000001256751517300217145ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/in_depth/http.rst000066400000000000000000000127351256751517300234350ustar00rootroot00000000000000HTTP implementation =================== HTTP client ``````````` At the heart of the HTTP client implementation is a single class aptly named ``basic_client``, which is also a template. The template ``basic_client`` takes three template parameters: .. code-block:: c++ namespace boost { namespace http { template struct basic_client; } // namespace http } // namespace boost The ``Tag`` template parameter follows the same tag-dispatch mechanism to determine the behavior of the ``basic_client``. The interface of ``basic_client`` may change depending on certain properties defined for the tag you provide. Below is a table of predefined supported tags you can use in your overload of the ``basic_client``: ------------ .. include:: http_client_tags.rst .. _Boost.Thread: http://www.boost.org/libs/thread The default typedef for the HTTP client that is provided uses the ``http_async_8bit_udp_resolve`` tag, and implements HTTP 1.1. The exact typedef is in the ``boost::network::http`` namespace as the following: .. code-block:: c++ namespace boost { namespace network { namespace http { typedef basic_client client; }}} This type has nested typedefs for the correct types for the ``basic_request`` and ``basic_response`` templates. To use the correct types for ``basic_request`` or ``basic_response`` you can use these nested typedefs like so: .. code-block:: c++ boost::network::http::client::request request; boost::network::http::client::response response; // or... using namespace boost::network; http::client::request request; http::client::response response; Typical use cases for the HTTP client would look something like the following: .. code-block:: c++ using namespace boost::network; http::request request("http://www.boost.org/"); request << header("Connection", "close"); The ``basic_client`` implements all HTTP methods as member functions (HEAD, GET, POST, PUT, DELETE). Therefore, the code to make an HTTP request looks trivially simple: .. code-block:: c++ using namespace boost::network; http::client client; http::client::request request("http://www.boost.org/"); http::client::response response = client.get(request); Accessing data from ``http::response`` is done using wrappers. To get the response headers, we use the ``headers`` wrapper which returns, in the default case, a multimap of strings to strings: .. code-block:: c++ using namespace boost::network; typedef headers_range::type response_headers; boost::range_iterator::type iterator; response_headers headers_ = headers(response); for (iterator it = headers_.begin(); it != headers_.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; } std::cout << std::endl; HTTP server ``````````` As with the HTTP client, the HTTP server that is provided with cpp-netlib is extensible through the tag mechanism and is embeddable. The template class declaration of ``basic_server`` is given below: .. code-block:: c++ namespace boost { namespace network { namespace http { template basic_server; }}} The second template argument is used to specify the request handler type. The request handler type is a functor type which should overload the function call operator (``RequestHandler::operator()`` should be overloaded) that takes two parameters: the first one being a reference to a ``const basic_request`` and the second being a reference to a ``basic_response`` instance. All the logic for parsing the HTTP request and building the ``const basic_request`` object resides internally in the ``basic_server`` template. Processing the request is delegated to the ``RequestHandler`` type, and the assumption of which would be that the response is formed inside the ``RequestHandler`` function call operator overload. The ``basic_server`` template however is only an underlying implementation while the user-visible implementation is the ``http::server`` template. This simply specializes the ``basic_server`` template to use the ``default_`` tag and forwards the ``RequestHandler`` parameter: .. code-block:: c++ namespace boost { namespace network { namespace http { template class server : public basic_server {}; }}} To use the forwarding server type you just supply the request handler implementation as the parameter. For example, an "echo" server example might look something like this: .. code-block:: c++ using namespace boost::network; struct echo; typedef http::server echo_server; struct echo { void operator () (const echo_server::request &request, echo_server::response &response) const { std::string ip = source(request); response = echo_server::response::stock_reply( echo_server::response::ok, body(request)); std::cerr << "[" << ip << "]: " << request.uri << " status = " << echo_server::response::ok << '\n'; } }; Here, all we're doing is returning the original request body with an HTTP OK response (200). We are also printing the IP address from where the request came from. Notice that we are using a wrapper to access the source of the request. cpp-netlib-0.11.2-final/libs/network/doc/in_depth/http_client_tags.rst000066400000000000000000000062631256751517300260100ustar00rootroot00000000000000+---------------------------------+---------------------------------------------+ | Tag | Description | +=================================+=============================================+ | http_default_8bit_tcp_resolve | This is the default HTTP implementation tag | | | that resolves addresses with a TCP resolver | | | and provides a synchronous/blocking HTTP | | | client interface. | +---------------------------------+---------------------------------------------+ | http_default_8bit_udp_resolve | This is similar to the above tag except that| | | it specifies the HTTP client to use a UDP | | | resolver. It also provides a synchronous/ | | | blocking HTTP client interface. | +---------------------------------+---------------------------------------------+ | http_keepalive_8bit_tcp_resolve | This tag specifies that the HTTP client by | | | default will keep connections to the server | | | alive. It only makes sense if the | | | ``version_major`` and ``version_minor`` are | | | both ``1``, to indicate HTTP 1.1. This tag | | | causes the HTTP client to resolve using a | | | TCP resolver and provides a synchronous/ | | | blocking HTTP client interface. | +---------------------------------+---------------------------------------------+ | http_keepalive_8bit_udp_resolve | This is similar to the above tag except that| | | it specifies the HTTP client to use a UDP | | | resolver. It also provides a synchronous/ | | | blocking HTTP client interface. | +---------------------------------+---------------------------------------------+ | http_async_8bit_tcp_resolve | This tag provides an active HTTP client | | | object implementation that uses a TCP | | | resolver. Response objects returned will | | | encapsulate a number of Boost.Thread_ | | | shared futures to hold values. Users don't | | | have to see this as they are implementation | | | details. | +---------------------------------+---------------------------------------------+ | http_async_8bit_udp_resolve | This is similar to the above tag except that| | | specifies the HTTP client to use a UDP | | | resolver. | +---------------------------------+---------------------------------------------+ .. _Boost.Thread: http://www.boost.org/libs/thread cpp-netlib-0.11.2-final/libs/network/doc/in_depth/message.rst000066400000000000000000000247231256751517300241020ustar00rootroot00000000000000The message template ==================== One of the core components in the library is the concept and the implementation of a common message type. In most (not all) network protocols, the concept of a message is central to the definition of the protocol. In HTTP, SMTP, XMPP, and even other protocols like SNMP and ICMP, there is a common notion of a "packet" or a message. In cpp-netlib we chose to implement the concept of a message that has the following common parts: * **Source** - every message has a source identifier which varies from protocol to protocol. * **Destination** - every message has a destination identifier which varies from protocol to protocol. * **Headers** - each message is assumed to contain headers, which may be empty in cases where the protocol does not support it, but is nonetheless supported by cpp-netlib messages. * **Body** - the content area of a message which varies from protocol to protocol (also sometimes referred to as payload). This division is purely logical -- in the underlying implementation, the message type can choose to have different means of storing the data, depending on the type used to tag the message. This section covers the `Message Concept`_ as well as the `basic_message`_ implementation. Message Concept ``````````````` .. warning:: The Message framework is deprecated in the 0.11 release, and will be removed in future versions of the library. The Message Concept specifies what the valid operations on a message are as well as what messages look like semantically. The following table summarize the operations and syntactic as well as semantic properties of messages. **Legend** :M: The message type. :H: A headers container type. :m,n: An instance of **M**. :S: A string type. :s,k,v: An instance of **S**. :O: The source type. :D: The destination type. :B: The body type. :T: The Tag type. +----------------------------+----------------------+-----------------------------------------+ | Construct | Result | Description | +============================+======================+=========================================+ | ``typename M::tag`` | T | The nested tag type. | +----------------------------+----------------------+-----------------------------------------+ | ``M()`` | Instance of M | Default constructible. | +----------------------------+----------------------+-----------------------------------------+ | ``M(m)`` | Instance of M | Copy constructible. | +----------------------------+----------------------+-----------------------------------------+ | ``m = n;`` | Reference to m | Assignable. | +----------------------------+----------------------+-----------------------------------------+ | ``swap(m, n);`` | ``void`` | Swappable. | +----------------------------+----------------------+-----------------------------------------+ | ``source(m);`` | Convertible to O | Retrieve the source of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``destination(m);`` | Convertible to D | Retrieve the destination of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``headers(m);`` | Convertible to H | Retrieve the headers of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``body(m);`` | Convertible to B | Retrieve the body of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``m << source(s);`` | ``M &`` | Set the source of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``m << destination(s);`` | ``M &`` | Set the destination of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``m << header(k, v);`` | ``M &`` | Add a header to ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``m << remove_header(k);`` | ``M &`` | Remove a header from ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``m << body(s);`` | ``M &`` | Set the body of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``source(m,s);`` | ``void`` | Set the source of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``destination(m,s);`` | ``void`` | Set the destination of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``add_header(m, k, v);`` | ``void`` | Add a header to ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``remove_header(m, k);`` | ``void`` | Remove a header from ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``clear_headers(m);`` | ``void`` | Clear the headers of ``m``. | +----------------------------+----------------------+-----------------------------------------+ | ``body(m,s);`` | ``M &`` | Set the body of ``m``. | +----------------------------+----------------------+-----------------------------------------+ Types that model the Message Concept are meant to encapsulate data that has a source, a destination, one or more named headers, and a body/payload. Because the accessors and the directives are not required to be part of the message type that models the Message Concept, a message can be implemented as a POD type and have all manipulations performed in the directive implementations, as well as value transformations done in the accessors. Directives, Modifiers, and Wrappers ``````````````````````````````````` In the Message Concept definition there are three basic constructs that follow a certain pattern. These patterns are Directives_, Modifiers_, and Wrappers_. Directives ~~~~~~~~~~ A directive is a function object that is applied to a Message. Directives encapsulate a set of operations that apply to messages. The general requirement for a Directive is that it should apply these operations on a message. A directive may dispatch on the type of the message passed to it at the point of the function call. Typically, directives are generated using a factory function that returns the correct directive type. For a given directive ``foo_directive`` a generator function called ``foo`` is typically implemented: .. code-block:: c++ struct foo_directive { template Message & operator()(Message & m) const { // do something to m return m; } }; foo_directive const foo() { return foo_directive(); } // to apply a directive, we use the << operator message m; m << foo(); Modifiers ~~~~~~~~~ A modifier is generally defined as a free function that takes a reference to a non-const lvalue message as the first parameter, and any number of parameters. In the concept definition of the Message Concept, a modifier follows the form: .. code-block:: c++ modifier(message, ...) Modifiers are meant to imply modifications on a message, which also allows for easier dispatch based on Argument Dependent Lookup (ADL_) on the type of the message. Note that Directives_ can be implemented in terms of Modifiers and vice versa, although that is not required nor specified. .. _ADL: http://en.wikipedia.org/wiki/Argument-dependent_name_lookup Wrappers ~~~~~~~~ A Wrapper is basically an implementation detail that ensures that a given message, when wrapped, can be converted to the associated part of the message. A wrapper has a type that encapsulates the conversion logic from a message to a given type. An example of a Wrapper would be ``source_wrapper`` which would be returned by a call to the wrapper generator function ``source``. An example implementation of the ``source_wrapper`` would look like: .. code-block:: c++ template class Message> struct source_wrapper { Message const & m; explicit source_wrapper(Message const & m) : m(m) {} typedef typename source::type source_type; operator source_type const & () { return m.source; } operator source_type const () { return m.source; } operator source_type () { return m.source; } }; template class Message> source_wrapper const source(Message const & message) { return source_wrapper(message); } This pattern is similar to an adapter, but the specific notion of wrapping a data type (in this case, an object of a type that models the Message Concept) using an intermediary wrapper is what is pertained to by the Wrapper pattern. In this case, the Wrapper is ``source_wrapper`` while ``source`` is merely a wrapper generator function. ``basic_message`` ````````````````` The default implementation of a simple type that models the Message Concept is available in cpp-netlib. This default implementation is named ``basic_message`` which supports a ``Tag`` template parameter. The definition of ``basic_message`` looks like this: .. code-block:: c++ template class basic_message; The ``basic_message`` template requires that the following tag-dispatched metafunctions are defined for the type ``Tag``: .. code-block:: c++ template struct string; template struct headers_container; All the operations defined by the message concept are implemented by this basic message type. Other message implementations can either use this common message type or specialize it according to whether they want to use different containers or whether it's going to be just a POD type. cpp-netlib-0.11.2-final/libs/network/doc/in_depth/uri.rst000066400000000000000000000134011256751517300232440ustar00rootroot00000000000000The URI class ============= In addition to protocol implementations, the :mod:`cpp-netlib` provides a powerful URI class. The class implements a parser based on `RFC 3986`_ and `RFC 2732`_. Generic URI syntax overview ``````````````````````````` A generic URI will take the form:: [scheme:]scheme-specific-part[#fragment] A URI is known as `absolute` if it specifies the scheme. Otherwise, it is known as a relative URI. Currently, ``uri`` supports only absolute URIs. URIs can be further classified according to whether they're hierarchical or opaque (non-hierarchical). Some examples of non-hierarchical URIs include:: mailto:john.doe@example.com news:comp.infosystems.www.servers.unix tel:+1-816-555-1212 The data following the first ``":"`` is said to be opaque to the URI parser and requires no further parsing. By way of example, the following shows how a non-hierarchical URI is processed by the parser by defining everything after the ``":"`` to be a part of the path: .. image:: ../_static/mailto_uri.png A hierarchical URI is identified by a double slash (``"//"``) after the scheme and a scheme-specific component, which `RFC 3986`_ defines to be:: [scheme:][//authority][path][?query][#fragment] The authority component can be further broken down to:: [user_info@]host[:port] Examples of hierarchical URIs include:: http://www.boost.org/ file:///bin/bash The following example, describing a complex URI using FTP, shows how a URI is broken down by the parser: .. image:: ../_static/ftp_uri.png Note that the ``authority`` is further subdivided into different elements. Another example, using HTTP is given below: .. image:: ../_static/http_uri.png The difference here between the path in a hierarchical URI and that in the example above for the non-hierarchical URI. The ``uri`` class ````````````````` As of version 0.9.3, ``uri`` supplies a URI parser and builder. To use the parser, it's as simple as supplying a string to the constructor: .. code-block:: c++ using namespace boost::network; uri::uri instance("http://cpp-netlib.github.com/"); assert(instance.is_valid()); std::cout << "scheme: " << instance.scheme() << std::endl << "host: " << instance.host() << std::endl; The command-line output of this program will be:: scheme: http host: cpp-netlib.github.com The ``uri`` builder ``````````````````` ``uri`` support a stream style syntax to create a URI from it's elements. For example the program: .. code-block:: c++ #include #include #include using namespace boost::network; int main() { uri::uri url; url << uri::scheme("http") << uri::host("www.github.com") << uri::path("/cpp-netlib"); std::cout << url << std::endl; return 0; } will output:: http://www.github.com/cpp-netlib ``URI Concept`` ``````````````` **Legend** :U: The URI type. :u,u_: An instance of **M**. :S: A string type. :s,v: An instance of **S**. :T: The Tag type. +----------------------------+----------------------+-----------------------------------------+ | Construct | Result | Description | +============================+======================+=========================================+ | ``U(u)`` | Instance of U | Copy constructible. | +----------------------------+----------------------+-----------------------------------------+ | ``U(s)`` | Instance of U | Constructible from string. | +----------------------------+----------------------+-----------------------------------------+ | ``u = u_;`` | Reference to u | Assignable. | +----------------------------+----------------------+-----------------------------------------+ | ``u = s;`` | Reference to u | Assignable from string. | +----------------------------+----------------------+-----------------------------------------+ | ``swap(u, u_);`` | ``void`` | Swappable. | +----------------------------+----------------------+-----------------------------------------+ | ``scheme(u);`` | Convertible to S | Retrieve the URI scheme of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``user_info(u);`` | Convertible to S | Retrieve the user info of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``host(u);`` | Convertible to S | Retrieve the host of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``port(u);`` | Convertible to H | Retrieve the port of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``path(u);`` | Convertible to S | Retrieve the path of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``query(u);`` | Convertible to S | Retrieve the query string of ``u``. | +----------------------------+----------------------+-----------------------------------------+ | ``fragment(u);`` | Convertible to S | Retrieve the fragment of ``u``. | +----------------------------+----------------------+-----------------------------------------+ .. _`RFC 3986`: http://tools.ietf.org/html/rfc3986 .. _`RFC 2368`: http://tools.ietf.org/html/rfc2368 .. _`RFC 3513`: http://tools.ietf.org/html/rfc3513 .. _`RFC 2732`: http://tools.ietf.org/html/rfc2732 cpp-netlib-0.11.2-final/libs/network/doc/index.rst000066400000000000000000000074371256751517300217760ustar00rootroot00000000000000.. _index: .. rubric:: Straightforward network programming in modern C++ .. :Authors: Glyn Matthews .. Dean Michael Berris .. :Date: 2014-10-01 .. :Version: 0.11.0 .. :Description: Complete user documentation, with examples, for the :mod:`cpp-netlib`. .. :Copyright: Copyright Glyn Matthews, Dean Michael Berris 2008-2013. .. Copyrigh 2013 Google, Inc. .. Distributed under the Boost Software License, Version .. 1.0. (See accompanying file LICENSE_1_0.txt or copy at .. http://www.boost.org/LICENSE_1_0.txt) Getting cpp-netlib ================== You can find out more about the :mod:`cpp-netlib` project at http://cpp-netlib.org/. **Download** You can get the latest official version of the library from the official project website at: http://cpp-netlib.org/ This version of :mod:`cpp-netlib` is tagged as cpp-netlib-0.11.0 in the GitHub_ repository. You can find more information about the progress of the development by checking our GitHub_ project page at: http://github.com/cpp-netlib/cpp-netlib **Support** You can ask questions, join the discussion, and report issues to the developers mailing list by joining via: https://groups.google.com/group/cpp-netlib You can also file issues on the Github_ issue tracker at: http://github.com/cpp-netlib/cpp-netlib/issues We are a growing community and we are happy to accept new contributions and ideas. C++ Network Library =================== :mod:`cpp-netlib` is a library collection that provides application layer protocol support using modern C++ techniques. It is light-weight, fast, portable and is intended to be as easy to configure as possible. Hello, world! ============= The :mod:`cpp-netlib` allows developers to write fast, portable network applications with the minimum of fuss. An HTTP server-client example can be written in tens of lines of code. The client is as simple as this: .. code-block:: cpp using namespace boost::network; using namespace boost::network::http; client::request request_("http://127.0.0.1:8000/"); request_ << header("Connection", "close"); client client_; client::response response_ = client_.get(request_); std::string body_ = body(response_); And the corresponding server code is listed below: .. code-block:: cpp namespace http = boost::network::http; struct handler; typedef http::server http_server; struct handler { void operator() (http_server::request const &request, http_server::response &response) { response = http_server::response::stock_reply( http_server::response::ok, "Hello, world!"); } void log(http_server::string_type const &info) { std::cerr << "ERROR: " << info << '\n'; } }; int main(int arg, char * argv[]) { handler handler_; http_server::options options(handler_); http_server server_( options.address("0.0.0.0") .port("8000")); server_.run(); } Want to learn more? =================== * :ref:`Take a look at the getting started guide ` * :ref:`Learn from some simple examples ` * :ref:`Find out what's new ` * :ref:`Study the library in more depth ` * :ref:`Discover more through the full reference ` * :ref:`Full table of contents ` .. warning:: Be aware that not all features are stable. The generic message design is under review and the URI and HTTP client implementation will continue to undergo refactoring. Future versions will include support for other network protocols. .. _Boost: http://www.boost.org/ .. _GitHub: http://github.com/ cpp-netlib-0.11.2-final/libs/network/doc/make.bat000066400000000000000000000060071256751517300215320ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation set SPHINXBUILD=sphinx-build set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\cpp-netlib.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\cpp-netlib.ghc goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end cpp-netlib-0.11.2-final/libs/network/doc/reference.rst000066400000000000000000000005311256751517300226110ustar00rootroot00000000000000.. _reference: Reference Manual ================ This reference manual refers to the API documentation of the public interfaces to the different client and/or server implementations within :mod:`cpp-netlib`. .. toctree:: :maxdepth: 2 reference/http_client reference/http_request reference/http_response reference/http_server cpp-netlib-0.11.2-final/libs/network/doc/reference/000077500000000000000000000000001256751517300220605ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/reference/http_client.rst000066400000000000000000000555361256751517300251450ustar00rootroot00000000000000 HTTP Client API =============== General ------- :mod:`cpp-netlib` includes and implements a number of HTTP clients that you can use and embed in your own applications. All of the HTTP client implementations: * **Cannot be copied.** This means you may have to store instances of the clients in dynamic memory if you intend to use them as function parameters or pass them around in smart pointers or by reference. * **Assume that requests made are independent of each other.** There currently is no cookie or session management system built-in to cpp-netlib's HTTP client implementations. The HTTP clients all share the same API, but the internals are documented in terms of what is different and what to expect with the different implementations. As of 0.9.1 the default implementation for the :mod:`cpp-netlib` HTTP client is asynchronous. As of 0.11 the `Synchronous Clients`_ are now *DEPRECATED* and will be removed in subsequent releases. Features -------- The HTTP client implementation supports requesting secure HTTP (HTTPS) content only in the following situations: * **Client libraries are built with ``BOOST_NETWORK_ENABLE_HTTPS``.** This tells the implementation to use HTTPS-specific code to handle HTTPS-based content when making connections associated with HTTPS URI's. This requires a dependency on OpenSSL_. * **The ``BOOST_NETWORK_ENABLE_HTTPS`` macro is set when compiling user code.** It is best to define this either at compile-time of all code using the library, or before including any of the client headers. To use the client implementations that support HTTPS URIs, you may explicitly do the following: .. code-block:: c++ #define BOOST_NETWORK_ENABLE_HTTPS #include This forces HTTPS support to be enabled and forces a dependency on OpenSSL_. This dependency is imposed by `Boost.Asio`_ .. _OpenSSL: http://www.openssl.org/ .. _`Boost.Asio`: http://www.boost.org/libs/asio Implementations --------------- There is a single user-facing template class named ``basic_client`` which takes three template parameters: * **Tag** - which static tag you choose that defines the behavior of the client. * **http_version_major** - an unsigned int that defines the HTTP major version number, this directly affects the HTTP messages sent by the client. * **http_version_minor** - an unsigned int that defines the HTTP minor version number. There are two major different class of implementations of the ``basic_client`` template that depend on which tag you choose: `Synchronous Clients`_ and `Asynchronous Clients`_. These two different classes are described in their own sections following this one. What follows is a table of all tags supported by the HTTP client implementation provided by :mod:`cpp-netlib`. --------------- .. include:: ../in_depth/http_client_tags.rst In the above table the tags follow a pattern for describing the behavior introduced by the tags. This pattern is shown below: ___ For example, the tag ``http_default_8bit_tcp_resolve`` indicates the protocol ``http``, a modifier ``default``, a character width of ``8bit``, and a resolve strategy of ``tcp_resolve``. Synchronous Clients ~~~~~~~~~~~~~~~~~~~ Of the client tags shown in the table, the following makes the ``basic_client`` behave as a fully synchronous client. * **http_default_8bit_tcp_resolve** * **http_default_8bit_udp_resolve** * **http_keepalive_8bit_tcp_resolve** * **http_keepalive_8bit_udp_resolve** The synchronous client implements all the operations of the client underneath the interface all block to wait for I/O to finish. All the member methods are synchronous and will block until the response object is ready or throws if errors are encountered in the performance of the HTTP requests. .. warning:: The synchronous clients are **NOT** thread safe. You will need to do external synchronization to use synchronous client implementations. .. note:: As of version 0.11, all the synchronous client implementations are deprecated. They will be removed in the next version of the library. Asynchronous Clients ~~~~~~~~~~~~~~~~~~~~ The following tags specify the ``basic_client`` to behave in an asynchronous manner: * **http_async_8bit_tcp_resolve** * **http_async_8bit_udp_resolve** An asynchronous client implementation means that``basic_client<...>`` is an `Active Object`_. This means that the client has and manages its own lifetime thread, and returns values that are asynchronously filled in. The response object encapsulates Boost.Thread_ futures which get filled in once the values are available. .. _Boost.Thread: http://www.boost.org/libs/thread .. _`Active Object`: http://en.wikipedia.org/wiki/Active_object The asynchronous clients implement all operations asynchronously which are hidden from the user. The interface is still synchronous but the fetching of data happens on a different thread. .. note:: The asynchronous clients are thread safe, and can be shared across many threads. Each request starts a sequence of asynchronous operations dedicated to that request. The client does not re-cycle connections and uses a one-request-one-connection model. When an asynchronous client object is destroyed, it waits for all pending asynchronous operations to finish. Errors encountered during operations on retrieving data from the response objects cause exceptions to be thrown -- therefore it is best that if a client object is constructed, it should outlive the response object or be outside the try-catch block handling the errors from operations on responses. In code, usage should look like the following: .. code-block:: c++ http::client client; try { http::client::response response = client.get("http://www.example.com/"); std::cout << body(response); } catch (std::exception& e) { // deal with exceptions here } A common mistake is to declare the client inside the try block which invokes undefined behavior when errors arise from the handling of response objects. Previous examples cited by the documentation showed the short version of the code which didn't bother moving the ``http::client`` object outside of the same ``try`` block where the request/response objects are being used. Member Functions ---------------- In this section we assume that the following typedef is in effect: .. code-block:: c++ typedef boost::network::http::basic_client< boost::network::http::tags::http_default_8bit_udp_resolve , 1 , 1 > client; Also, that code using the HTTP client will have use the following header: .. code-block:: c++ #include .. note:: Starting version 0.9, cpp-netlib clients and server implementations by default now have an externally-linked component. This is a breaking change for code that used to rely on cpp-netlib being a header-only library, but can inhibited by defining the ``BOOST_NETWORK_NO_LIB`` preprocessor macro before including any cpp-netlib header. .. note:: Starting version 0.11, cpp-netlib clients and server implementations no longer support the ``BOOST_NETWORK_NO_LIB`` option. Constructors ~~~~~~~~~~~~ The client implementation can be default constructed, or customized at initialization. ``client()`` Default constructor. ``explicit client(client::options const &)`` Constructor taking a ``client_options`` object. The following table shows the options you can set on a ``client_options`` instance. +--------------------------+----------------------------+--------------------------+ | Parameter Name | Type | Description | +==========================+============================+==========================+ | follow_redirects | ``bool`` | Boolean to specify | | | | whether the client | | | | should follow HTTP | | | | redirects. Default is | | | | ``false``. | +--------------------------+----------------------------+--------------------------+ | cache_resolved | ``bool`` | Boolean to specify | | | | whether the client | | | | should cache resolved | | | | endpoints. The default | | | | is ``false``. | +--------------------------+----------------------------+--------------------------+ | io_service | ``shared_ptr`` | Shared pointer to a | | | | Boost.Asio | | | | ``io_service``. | +--------------------------+----------------------------+--------------------------+ | openssl_certificate | ``string`` | The filename of the | | | | certificate to load for | | | | the SSL connection for | | | | verification. | +--------------------------+----------------------------+--------------------------+ | openssl_verify_path | ``string`` | The directory from | | | | which the certificate | | | | authority files are | | | | located. | +--------------------------+----------------------------+--------------------------+ | always_verify_peer | ``bool`` | Boolean to specify | | | | whether the client | | | | should always verify | | | | peers in SSL connections | +--------------------------+----------------------------+--------------------------+ | openssl_certificate_file | ``string`` | Filename of the | | | | certificate to use for | | | | client-side SSL session | | | | establishment. | +--------------------------+----------------------------+--------------------------+ | openssl_private_key_file | ``string`` | Filename of the | | | | private key to use for | | | | client-side SSL session | | | | establishment. | +--------------------------+----------------------------+--------------------------+ | timeout | ``int`` | Number of seconds to | | | | wait for client requests | | | | before considering a | | | | timeout has occurred. | +--------------------------+----------------------------+--------------------------+ To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ using namespace boost::network::http; // parameters are in this namespace client::options options; options.follow_redirects(true) .cache_resolved(true) .io_service(boost::make_shared()) .openssl_certificate("/tmp/my-cert") .openssl_verify_path("/tmp/ca-certs") .timeout(10); client client_(options); // use client_ as normal from here on out. HTTP Methods ~~~~~~~~~~~~ The client implementation supports various HTTP methods. The following constructs assume that a client has been properly constructed named ``client_`` and that there is an appropriately constructed request object named ``request_`` and that there is an appropriately constructed response object named ``response_`` like the following: .. code-block:: c++ using namespace boost::network::http; // parameters are here client client_(); client::request request_("http://cpp-netib.github.com/"); client::response response_; ``response_ = client_.get(request_)`` Perform an HTTP GET request. ``response_ = client_.get(request_, callback)`` Perform an HTTP GET request, and have the body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.head(request_)`` Perform an HTTP HEAD request. ``response_ = client_.post(request_)`` Perform an HTTP POST, use the data already set in the request object which includes the headers, and the body. ``response_ = client_.post(request_, callback)`` Perform an HTTP POST request, and have the body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.post(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. ``response_ = client_.post(request_, body, callback)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.post(request_, body, content_type)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. ``response_ = client_.post(request_, body, content_type, callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.post(request_, body, content_type, callback, streaming_callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. The ``streaming_callback`` argument should have a which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent. ``response_ = client_.post(request_, streaming_callback)`` Perform and HTTP POST request, and have the request's body chunks be generated by the ``streaming_callback`` which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent. ``response_ = client_.post(request_, callback, streaming_callback)`` Perform an HTTP POST request, and have the body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. This form also has the request's body chunks be generated by the ``streaming_callback`` which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent. ``response_ = client_.put(request_)`` Perform an HTTP PUT, use the data already set in the request object which includes the headers, and the body. ``response_ = client_.put(request_, callback)`` Perform an HTTP PUT request, and have the body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.put(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. ``response_ = client_.put(request_, body, callback)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.put(request_, body, content_type)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. ``response_ = client_.put(request_, body, content_type, callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. ``response_ = client_.put(request_, body, content_type, callback, streaming_callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. This form also has the request's body chunks be generated by the ``streaming_callback`` which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent ``response_ = client_.put(request_, streaming_callback)`` Perform and HTTP PUT request, and have the request's body chunks be generated by the ``streaming_callback`` which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent. ``response_ = client_.put(request_, callback, streaming_callback)`` Perform an HTTP PUT request, and have the body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. This form also has the request's body chunks be generated by the ``streaming_callback`` which has a signature of the form: ``bool(string_type&)``. The provided ``string_type&`` will be streamed as soon as the function returns. A return value of ``false`` signals the client that the most recent invocation is the last chunk to be sent. ``response_ = client_.delete_(request_)`` Perform an HTTP DELETE request. ``response_ = client_.delete_(request_, body_handler=callback)`` Perform an HTTP DELETE request, and have the response body chunks be handled by the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. Client-Specific ~~~~~~~~~~~~~~~ ``client_.clear_resolved_cache()`` Clear the cache of resolved endpoints. Streaming Body Handler ~~~~~~~~~~~~~~~~~~~~~~ As of v0.9.1 the library now offers a way to support a streaming body callback function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). A convenience macro is also provided to make callback handlers easier to write. This macro is called ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` which allows users to write the following code to easily create functions or function objects that are compatible with the callback function requirements. An example of how to use the macro is shown below: .. code-block:: c++ struct body_handler { explicit body_handler(std::string & body) : body(body) {} BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { // in here, range is the Boost.Range iterator_range, and error is // the Boost.System error code. if (!error) body.append(boost::begin(range), boost::end(range)); } std::string & body; }; // somewhere else std::string some_string; response_ = client_.get(request("http://cpp-netlib.github.com/"), body_handler(some_string)); You can also use if for standalone functions instead if you don't want or need to create a function object. .. code-block:: c++ BOOST_NETWORK_HTTP_BODY_CALLBACK(print_body, range, error) { if (!error) std::cout << "Received " << boost::distance(range) << "bytes." << std::endl; else std::cout << "Error: " << error << std::endl; } // somewhere else response_ = client_.get(request("http://cpp-netlib.github.com/"), print_body); The ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` macro is defined in ``boost/network/protocol/http/client/macros.hpp``. cpp-netlib-0.11.2-final/libs/network/doc/reference/http_request.rst000066400000000000000000000316521256751517300253500ustar00rootroot00000000000000 HTTP Request ============ This part of the documentation talks about the publicly accessible API of the HTTP Request objects. This section details the `Request Concepts`_ requirements, the implemented and required Directives_, Modifiers_, and Wrappers_ that work with the HTTP Request objects. Request Concepts ---------------- There are two generally supported Request Concepts implemented in the library. The first of two is the `Normal Client Request Concept`_ and the second is the `Pod Server Request Concept`_. The `Normal Client Request Concept`_ is what the HTTP Client interface requires. All operations performed internally by the HTTP Client abide by the interface required by this concept definition. The `Pod Server Request Concept`_ is as the name suggests what the HTTP Server implementation requires from Request Objects. Switching on whether the `Request` concept chooses either of the `Normal Client Request Concept`_ or the `Pod Server Request Concept`_ is done through the nested ``tag`` type and whether that tag derives from the root tag ``pod``. Simply, if the Request type's nested ``tag`` type derives from ``boost::network::tags::pod`` then it chooses to enforce the `Pod Server Request Concept`_, otherwise it chooses the `Normal Client Request Concept`_. Normal Client Request Concept ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A type models the Normal Client Request Concept if it models the `Message Concept`_ and also supports the following constructs. **Legend** :R: The request type. :r: An instance of R. :S: The string type. :s: An instance of S. :P: The port type. :p: An instance of P. +-----------------------+-------------+----------------------------------------+ | Construct | Result | Description | +=======================+=============+========================================+ | ``R::string_type`` | ``S`` | The nested ``string_type`` type. | +-----------------------+-------------+----------------------------------------+ | ``R::port_type`` | ``P`` | The nested ``port_type`` type. | +-----------------------+-------------+----------------------------------------+ | ``R r(s)`` | **NA** | Construct a Request with an ``s`` | | | | provided. This treats ``s`` as the URI | | | | to where the request is destined for. | +-----------------------+-------------+----------------------------------------+ | ``host(request)`` | Convertible | Return the host to where the request | | | to ``S`` | is destined for. | +-----------------------+-------------+----------------------------------------+ | ``port(request)`` | Convertible | Return the port to where the request | | | to ``P`` | is destined for. | +-----------------------+-------------+----------------------------------------+ | ``path(request)`` | Convertible | Return the path included in the URI. | | | to ``S`` | | +-----------------------+-------------+----------------------------------------+ | ``query(request)`` | Convertible | Return the query part of the URI. | | | to ``S`` | | +-----------------------+-------------+----------------------------------------+ | ``anchor(request)`` | Convertible | Return the anchor part of the URI. | | | to ``S`` | | +-----------------------+-------------+----------------------------------------+ | ``protocol(request)`` | Convertible | Return the protocol/scheme part of the | | | to ``S`` | URI. | +-----------------------+-------------+----------------------------------------+ | ``r << uri(s)`` | ``R&`` | Set the URI of the request. | +-----------------------+-------------+----------------------------------------+ | ``uri(r, s)`` | ``void`` | Set the URI of the request. | +-----------------------+-------------+----------------------------------------+ Pod Server Request Concept ~~~~~~~~~~~~~~~~~~~~~~~~~~ A type models the Pod Server Request Concept if it models the `Message Concept`_ and also supports the following constructs. **Legend** :R: The request type. :r: An instance of R. :S: The string type. :I: An unsigned 8 bit integer. :V: The vector type for headers. +-------------------------------+--------+-------------------------------------+ | Construct | Result | Description | +===============================+========+=====================================+ | ``R::string_type`` | ``S`` | The nested ``string_type`` type. | +-------------------------------+--------+-------------------------------------+ | ``R::headers_container_type`` | ``V`` | The nested | | | | ``headers_container_type`` type. | +-------------------------------+--------+-------------------------------------+ | ``r.source`` | ``S`` | The nested source of the request. | +-------------------------------+--------+-------------------------------------+ | ``r.method`` | ``S`` | The method of the request. | +-------------------------------+--------+-------------------------------------+ | ``r.destination`` | ``S`` | The destination of the request. | | | | This is normally the URI of the | | | | request. | +-------------------------------+--------+-------------------------------------+ | ``r.version_major`` | ``I`` | The major version number part of | | | | the request. | +-------------------------------+--------+-------------------------------------+ | ``r.version_minor`` | ``I`` | The minor version number part of | | | | the request. | +-------------------------------+--------+-------------------------------------+ | ``r.headers`` | ``V`` | The vector of headers. | +-------------------------------+--------+-------------------------------------+ | ``r.body`` | ``S`` | The body of the request. | +-------------------------------+--------+-------------------------------------+ .. _Message Concept: ../in_depth/message.html#message-concept Directives ---------- This section details the provided directives that are provided by :mod:`cpp-netlib`. The section was written to assume that an appropriately constructed request instance is either of the following: .. code-block:: c++ boost::network::http::basic_request< boost::network::http::tags::http_default_8bit_udp_resolve > request; // or boost::network::http::basic_request< boost::network::http::tags::http_server > request; The section also assumes that there following using namespace declaration is in effect: .. code-block:: c++ using namespace boost::network; Directives are meant to be used in the following manner: .. code-block:: c++ request << directive(...); .. warning:: There are two versions of directives, those that are applicable to messages that support narrow strings (``std::string``) and those that are applicable to messages that support wide strings (``std::wstring``). The :mod:`cpp-netlib` implementation still does not convert wide strings into UTF-8 encoded narrow strings. This will be implemented in subsequent library releases. For now all the implemented directives are listed, even if some of them still do not implement things correctly. *unspecified* ``source(std::string const & source_)`` Create a source directive with a ``std::string`` as a parameter, to be set as the source of the request. *unspecified* ``source(std::wstring const & source_)`` Create a source directive with a ``std::wstring`` as a parameter, to be set as the source of the request. *unspecified* ``destination(std::string const & source_)`` Create a destination directive with a ``std::string`` as a parameter, to be set as the destination of the request. *unspecified* ``destination(std::wstring const & source_)`` Create a destination directive with a ``std::wstring`` as a parameter, to be set as the destination of the request. *unspecified* ``header(std::string const & name, std::string const & value)`` Create a header directive that will add the given name and value pair to the headers already associated with the request. In this case the name and values are both ``std::string``. *unspecified* ``header(std::wstring const & name, std::wstring const & value)`` Create a header directive that will add the given name and value pair to the headers already associated with the request. In this case the name and values are both ``std::wstring``. *unspecified* ``remove_header(std::string const & name)`` Create a remove_header directive that will remove all the occurences of the given name from the headers already associated with the request. In this case the name of the header is of type ``std::string``. *unspecified* ``remove_header(std::wstring const & name)`` Create a remove_header directive that will remove all the occurences of the given name from the headers already associated with the request. In this case the name of the header is of type ``std::wstring``. *unspecified* ``body(std::string const & body_)`` Create a body directive that will set the request's body to the given parameter. In this case the type of the body is an ``std::string``. *unspecified* ``body(std::wstring const & body_)`` Create a body directive that will set the request's body to the given parameter. In this case the type of the body is an ``std::wstring``. Modifiers --------- This section details the provided modifiers that are provided by :mod:`cpp-netlib`. ``template inline void source(basic_request & request, typename string::type const & source_)`` Modifies the source of the given ``request``. The type of ``source_`` is dependent on the ``Tag`` specialization of ``basic_request``. ``template inline void destination(basic_request & request, typename string::type const & destination_)`` Modifies the destination of the given ``request``. The type of ``destination_`` is dependent on the ``Tag`` specialization of ``basic_request``. ``template inline void add_header(basic_request & request, typename string::type const & name, typename string::type const & value)`` Adds a header to the given ``request``. The type of the ``name`` and ``value`` parameters are dependent on the ``Tag`` specialization of ``basic_request``. ``template inline void remove_header(basic_request & request, typename string::type const & name)`` Removes a header from the given ``request``. The type of the ``name`` parameter is dependent on the ``Tag`` specialization of ``basic_request``. ``template inline void clear_headers(basic_request & request)`` Removes all headers from the given ``request``. ``template inline void body(basic_request & request, typename string::type const & body_)`` Modifies the body of the given ``request``. The type of ``body_`` is dependent on the ``Tag`` specialization of ``basic_request``. Wrappers -------- This section details the provided request wrappers that come with :mod:`cpp-netlib`. Wrappers are used to convert a message into a different type, usually providing accessor operations to retrieve just part of the message. This section assumes that the following using namespace directives are in effect: .. code-block:: c++ using namespace boost::network; using namespace boost::network::http; ``template `` *unspecified* ``source(basic_request const & request)`` Returns a wrapper convertible to ``typename string::type`` that provides the source of a given request. ``template `` *unspecified* ``destination(basic_request const & request)`` Returns a wrapper convertible to ``typename string::type`` that provides the destination of a given request. ``template `` *unspecified* ``headers(basic_request const & request)`` Returns a wrapper convertible to ``typename headers_range >::type`` or ``typename basic_request::headers_container_type`` that provides the headers of a given request. ``template `` *unspecified* ``body(basic_request const & request)`` Returns a wrapper convertible to ``typename string::type`` that provides the body of a given request. cpp-netlib-0.11.2-final/libs/network/doc/reference/http_response.rst000066400000000000000000000433441256751517300255170ustar00rootroot00000000000000 HTTP Response ============= This part of the documentation talks about the publicly accessible API of the HTTP Response objects. This section details the `Response Concept`_ requirements, the implemented and required Directives_, Modifiers_, and Wrappers_ that work with the HTTP Response objects. .. note:: The HTTP server response object is a POD type, which doesn't support any of the following details. There are only a few fields available in the HTTP server response type, which can be seen in ``boost/network/protocol/http/impl/response.ipp``. Response Concept ---------------- A type models the Response Concept if it models the `Message Concept`_ and also supports the following constructs. **Legend** :R: The response type. :r: An instance of R. :S: The string type. :s,e,g: Instances of S. :P: The port type. :p: An instance of P. :V: The version type. :v: An instance of v. :T: The status type. :t: An instance of T. :M: The status message type. :m: An instance of M. :U: An unsigned 16-bit int. :u: An instance of U. .. note:: In the table below, the namespace ``traits`` is an alias for ``boost::network::http::traits``. +-------------------------------------+----------+-----------------------------+ | Construct | Result | Description | +=====================================+==========+=============================+ | ``R::string_type`` | ``S`` | The nested ``string_type`` | | | | type. | +-------------------------------------+----------+-----------------------------+ | ``traits::version::type`` | ``V`` | The version type associated | | | | with R. | +-------------------------------------+----------+-----------------------------+ | ``traits::status::type`` | ``T`` | The status type associated | | | | with R. | +-------------------------------------+----------+-----------------------------+ | ``traits::status_message::type`` | ``M`` | The status message type | | | | associated with R. | +-------------------------------------+----------+-----------------------------+ | ``r << version(v)`` | ``R&`` | Sets the version of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``r << status(t)`` | ``R&`` | Sets the status of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``r << status_message(m)`` | ``R&`` | Sets the status message of | | | | ``r``. | +-------------------------------------+----------+-----------------------------+ | ``version(r, v)`` | ``void`` | Sets the version of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``status(r, t)`` | ``void`` | Sets the status of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``status_message(r, m)`` | ``void`` | Sets the status message of | | | | ``r``. | +-------------------------------------+----------+-----------------------------+ | ``S e = version(r)`` | **NA** | Get the version of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``U u = status(r)`` | **NA** | Get the status of ``r``. | +-------------------------------------+----------+-----------------------------+ | ``S g = status_message(r)`` | **NA** | Get the status message of | | | | ``r``. | +-------------------------------------+----------+-----------------------------+ .. _Message Concept: ../in_depth/message.html#message-concept Directives ---------- This section details the provided directives that are provided by :mod:`cpp-netlib`. The section was written to assume that an appropriately constructed response instance is either of the following: .. code-block:: c++ boost::network::http::basic_response< boost::network::http::tags::http_default_8bit_udp_resolve > response; // or boost::network::http::basic_response< boost::network::http::tags::http_server > response; The section also assumes that there following using namespace declaration is in effect: .. code-block:: c++ using namespace boost::network; Directives are meant to be used in the following manner: .. code-block:: c++ response << directive(...); .. warning:: There are four versions of directives, those that are applicable to messages that support narrow strings (``std::string``), those that are applicable to messages that support wide strings (``std::wstring``), those that are applicable to messages that support future-wrapped narrow and wide strings (``boost::shared_future`` and ``boost::shared_future``). The :mod:`cpp-netlib` implementation still does not convert wide strings into UTF-8 encoded narrow strings. This will be implemented in subsequent library releases. For now all the implemented directives are listed, even if some of them still do not implement things correctly. *unspecified* ``source(std::string const & source_)`` Create a source directive with a ``std::string`` as a parameter, to be set as the source of the response. *unspecified* ``source(std::wstring const & source_)`` Create a source directive with a ``std::wstring`` as a parameter, to be set as the source of the response. *unspecified* ``source(boost::shared_future const & source_)`` Create a source directive with a ``boost::shared_future`` as a parameter, to be set as the source of the response. *unspecified* ``source(boost::shared_future const & source_)`` Create a source directive with a ``boost::shared_future`` as a parameter, to be set as the source of the response. *unspecified* ``destination(std::string const & source_)`` Create a destination directive with a ``std::string`` as a parameter, to be set as the destination of the response. *unspecified* ``destination(std::wstring const & source_)`` Create a destination directive with a ``std::wstring`` as a parameter, to be set as the destination of the response. *unspecified* ``destination(boost::shared_future const & destination_)`` Create a destination directive with a ``boost::shared_future`` as a parameter, to be set as the destination of the response. *unspecified* ``destination(boost::shared_future const & destination_)`` Create a destination directive with a ``boost::shared_future`` as a parameter, to be set as the destination of the response. *unspecified* ``header(std::string const & name, std::string const & value)`` Create a header directive that will add the given name and value pair to the headers already associated with the response. In this case the name and values are both ``std::string``. *unspecified* ``header(std::wstring const & name, std::wstring const & value)`` Create a header directive that will add the given name and value pair to the headers already associated with the response. In this case the name and values are both ``std::wstring``. *unspecified* ``remove_header(std::string const & name)`` Create a remove_header directive that will remove all the occurences of the given name from the headers already associated with the response. In this case the name of the header is of type ``std::string``. *unspecified* ``remove_header(std::wstring const & name)`` Create a remove_header directive that will remove all the occurences of the given name from the headers already associated with the response. In this case the name of the header is of type ``std::wstring``. *unspecified* ``body(std::string const & body_)`` Create a body directive that will set the response's body to the given parameter. In this case the type of the body is an ``std::string``. *unspecified* ``body(std::wstring const & body_)`` Create a body directive that will set the response's body to the given parameter. In this case the type of the body is an ``std::wstring``. *unspecified* ``body(boost::shared_future const & body_)`` Create a body directive that will set the response's body to the given parameter. In this case the type of the body is an ``boost::shared_future``. *unspecified* ``body(boost::shared_future const & body_)`` Create a body directive that will set the response's body to the given parameter. In this case the type of the body is an ``boost::shared_future``. *unspecified* ``version(std::string const & version_)`` Create a version directive that will set the response's version to the given parameter. In this case the type of the version is an ``std::string``. Note that this version includes the full ``"HTTP/"`` string. *unspecified* ``version(std::wstring const & version_)`` Create a version directive that will set the response's version to the given parameter. In this case the type of the version is an ``std::wstring``. Note that this version includes the full ``"HTTP/"`` string. *unspecified* ``version(boost::shared_future const & version_)`` Create a version directive that will set the response's version to the given parameter. In this case the type of the version is an ``boost::shared_future``. Note that this version includes the full ``"HTTP/"`` string. *unspecified* ``version(boost::shared_future const & version_)`` Create a version directive that will set the response's version to the given parameter. In this case the type of the version is an ``boost::shared_future``. Note that this version includes the full ``"HTTP/"`` string. *unspecified* ``status_message(std::string const & status_message_)`` Create a status_message directive that will set the response's status_message to the given parameter. In this case the type of the status_message is an ``std::string``. Note that this status_message includes the full ``"HTTP/"`` string. *unspecified* ``status_message(std::wstring const & status_message_)`` Create a status_message directive that will set the response's status_message to the given parameter. In this case the type of the status_message is an ``std::wstring``. Note that this status_message includes the full ``"HTTP/"`` string. *unspecified* ``status_message(boost::shared_future const & status_message_)`` Create a status_message directive that will set the response's status_message to the given parameter. In this case the type of the status_message is an ``boost::shared_future``. Note that this status_message includes the full ``"HTTP/"`` string. *unspecified* ``status_message(boost::shared_future const & status_message_)`` Create a status_message directive that will set the response's status_message to the given parameter. In this case the type of the status_message is an ``boost::shared_future``. Note that this status_message includes the full ``"HTTP/"`` string. *unspecified* ``status(boost::uint16_t status_)`` Create a status directive that will set the response's status to the given parameter. In this case the type of ``status_`` is ``boost::uint16_t``. *unspecified* ``status(boost::shared_future const & status_)`` Create a status directive that will set the response's status to the given parameter. In this case the type of ``status_`` is ``boost::shared_future``. Modifiers --------- This section details the provided modifiers that are provided by :mod:`cpp-netlib`. ``template inline void source(basic_response & response, typename string::type const & source_)`` Modifies the source of the given ``response``. The type of ``source_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void source(basic_response & response, boost::shared_future::type> const & source_)`` Modifies the source of the given ``response``. The type of ``source_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void destination(basic_response & response, typename string::type const & destination_)`` Modifies the destination of the given ``response``. The type of ``destination_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void destination(basic_response & response, boost::shared_future::type> const & destination_)`` Modifies the destination of the given ``response``. The type of ``destination_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void add_header(basic_response & response, typename string::type const & name, typename string::type const & value)`` Adds a header to the given ``response``. The type of the ``name`` and ``value`` parameters are dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void remove_header(basic_response & response, typename string::type const & name)`` Removes a header from the given ``response``. The type of the ``name`` parameter is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void headers(basic_response & response, typename headers_container >::type const & headers_)`` Sets the whole headers contained in ``response`` as the given parameter ``headers_``. ``template inline void headers(basic_response & response, boost::shared_future >::type> const & headers_)`` Sets the whole headers contained in ``response`` as the given parameter ``headers_``. ``template inline void clear_headers(basic_response & response)`` Removes all headers from the given ``response``. ``template inline void body(basic_response & response, typename string::type const & body_)`` Modifies the body of the given ``response``. The type of ``body_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void body(basic_response & response, boost::shared_future::type> const & body_)`` Modifies the body of the given ``response``. The type of ``body_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void version(basic_response & response, typename traits::version >::type const & version_)`` Modifies the version of the given ``response``. The type of ``version_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void status(basic_response & response, typename traits::status >::type const & status_)`` Modifies the status of the given ``response``. The type of ``status_`` is dependent on the ``Tag`` specialization of ``basic_response``. ``template inline void status_message(basic_response & response, typename traits::status_message >::type const & status_message_)`` Modifies the status message of the given ``response``. The type of ``status_message_`` is dependent on the ``Tag`` specialization of ``basic_response``. Wrappers -------- This section details the provided response wrappers that come with :mod:`cpp-netlib`. Wrappers are used to convert a message into a different type, usually providing accessor operations to retrieve just part of the message. This section assumes that the following using namespace directives are in effect: .. code-block:: c++ using namespace boost::network; using namespace boost::network::http; ``template `` *unspecified* ``source(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the source of a given response. ``template `` *unspecified* ``destination(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the destination of a given response. ``template `` *unspecified* ``headers(basic_response const & response)`` Returns a wrapper convertible to ``typename headers_range >::type`` or ``typename basic_response::headers_container_type`` that provides the headers of a given response. ``template `` *unspecified* ``body(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the body of a given response. ``template `` *unspecified* ``version(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the version of the given response. ``template `` *unspecified* ``status(basic_response const & response)`` Returns a wrapper convertible to ``typename boost::uint16_t`` that provides the status of the given response. ``template `` *unspecified* ``status_message(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the status message of the given response. cpp-netlib-0.11.2-final/libs/network/doc/reference/http_server.rst000066400000000000000000000654431256751517300251730ustar00rootroot00000000000000 HTTP Server API =============== General ------- :mod:`cpp-netlib` includes and implements two distinct HTTP server implementations that you can use and embed in your own applications. Both HTTP Server implementations: * **Cannot be copied.** This means you may have to store instances of the HTTP Server in dynamic memory if you intend to use them as function parameters or pass them around in smart pointers of by reference. * **Assume that requests made are independent of each other.** None of the HTTP Server implementations support request pipelining (yet) so a single connection only deals with a single request. * **Are header-only and are compiled-into your application.** Future releases in case you want to upgrade the implementation you are using in your application will be distributed as header-only implementations, which means you have to re-compile your application to use a newer version of the implementations. The HTTP Servers have different semantics, and in some cases require different APIs from the supplied template parameters. Implementations --------------- There are two different user-facing template classes that differentiate the `Synchronous Servers`_ from the `Asynchronous Servers`_. Both templates take a single template parameter named ``Handler`` which describes the type of the Handler function object. There are two different Handler concepts, one concept for `Synchronous Servers`_ and another for `Asynchronous Servers`. The SynchronousHandler concept for `Synchronous Servers`_ is described by the following table: --------------- **Legend:** H The Handler type. h An instance of H. Req A type that models the Request Concept. Res A type that models the Response Concept. req An instance of Req. res An instance of Res. +----------------+-------------+----------------------------------------------+ | Construct | Return Type | Description | +================+=============+==============================================+ | ``h(req,res)`` | ``void`` | Handle the request; res is passed in as a | | | | non-const lvalue, which represents the | | | | response to be returned to the client | | | | performing the request. | +----------------+-------------+----------------------------------------------+ More information about the internals of the `Synchronous Servers`_ can be found in the following section. The AsynchronousHandler concept for `Asynchronous Servers`_ is described by the following table: --------------- **Legend:** H The Handler type. h An instance of H. Req A type that models the Request Concept. ConnectionPtr A type that models the Connection Pointer Concept. req An instance of Req. conn An instance of ConncetionPtr. +------------------+-------------+--------------------------------------------+ | Construct | Return Type | Description | +==================+=============+============================================+ | ``h(req, conn)`` | ``void`` | Handle the request; conn is a shared | | | | pointer which exposes functions for | | | | writing to and reading from the connection.| +------------------+-------------+--------------------------------------------+ More information about the internals of the `Asynchronous Servers`_ can be found in the following section. Synchronous Servers ------------------- The synchronous server implementation is represented by the template ``server`` in namespace ``boost::network::http``. The ``server`` template takes in a single template parameter named ``Handler`` which models the SynchronousHandler concept (described above). An instance of Handler is taken in by reference to the constructor of the HTTP server. This means the Handler is not copied around and only a single instance of the handler is used for all connections and requests performed against the HTTP server. .. warning:: It is important to note that the HTTP server does not implement any locking upon invoking the Handler. In case you have any state in the Handler that will be associated with the synchronous server, you would have to implement your own synchronization internal to the Handler implementation. This matters especially if you run the synchronous server in multiple threads. The general pattern of usage for the HTTP Server template is shown below: .. code-block:: c++ struct handler; typedef boost::network::http::server http_server; struct handler { void operator()( http_server::request const & req, http_server::response & res ) { // do something, and then edit the res object here. } }; More information about the actual HTTP Server API follows in the next section. It is important to understand that the HTTP Server is actually embedded in your application, which means you can expose almost all your application logic through the Handler type, which you can also initialize appropriately. API Documentation ~~~~~~~~~~~~~~~~~ The following sections assume that the following file has been included: .. code-block:: c++ #include And that the following typedef's have been put in place: .. code-block:: c++ struct handler_type; typedef boost::network::http::server http_server; struct handler_type { void operator()(http_server::request const & request, http_server::response & response) { // do something here } }; Constructor ``````````` ``explicit http_server(options)`` Construct an HTTP Server instance, passing in a ``server_options`` object. The following table shows the supported options in ``server_options``. +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | Parameter Name | Type | Description | +=======================+==========================================+==================================================================================================+ | address | string_type | The hostname or IP address from which the server should be bound to. This parameter is required. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | port | string_type | The port to which the server should bind and listen to. This parameter is required. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | thread_pool | ``shared_ptr`` | A shared pointer to an instance of ``boost::network::utils::thread_pool`` -- this is the | | | | thread pool from where the handler is invoked. This parameter is only applicable and required | | | | for ``async_server`` instances. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | io_service | ``shared_ptr`` | An optional lvalue to an instance of ``boost::asio::io_service`` which allows the server to use | | | | an already-constructed ``boost::asio::io_service`` instance instead of instantiating one that it | | | | manages. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | reuse_address | ``bool`` | A boolean that specifies whether to re-use the address and port on which the server will be | | | | bound to. This enables or disables the socket option for listener sockets. The default is | | | | ``false``. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | report_aborted | ``bool`` | A boolean that specifies whether the listening socket should report aborted connection attempts | | | | to the accept handler (an internal detail of cpp-netlib). This is put in place to allow for | | | | future-proofing the code in case an optional error handler function is supported in later | | | | releases of cpp-netlib. The default is ``false``. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | receive_buffer_size | ``int`` | The size of the socket's receive buffer. The default is defined by Boost.Asio and is | | | | platform-dependent. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | send_buffer_size | ``int`` | The size of the socket's send buffer. The default is defined by Boost.Asio and is | | | | platform-dependent. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | receive_low_watermark | ``int`` | The size of the socket's low watermark for its receive buffer. The default is defined by | | | | Boost.Asio and is platform-dependent. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | send_buffer_size | ``int`` | The size of the socket's send low watermark for its send buffer. The default is defined by | | | | Boost.Asio and is platform-dependent. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | non_blocking_io | ``bool`` | An optional bool to define whether the socket should use non-blocking I/O in case the platform | | | | supports it. The default is ``true``. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | linger | ``bool`` | An optional bool to determine whether the socket should linger in case there's still data to be | | | | sent out at the time of its closing. The default is ``true``. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | linger_timeout | ``int`` | An optional int to define the timeout to wait for socket closes before it is set to linger. | | | | The default is ``0``. | +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ | context | ``shared_ptr`` | An optional shared pointer to an instance of ``boost::asio::ssl::context`` -- this contains the | | | | settings needed to support SSL. This parameter is only applicable for ``async_server`` instances.| +-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ using namespace boost::network::http; // parameters are in this namespace handler handler_instance; sync_server::options options(handler_instance); options.address("0.0.0.0") .port("80") .io_service(boost::make_shared()) .reuse_address(true); sync_server instance(options); instance.run(); Public Members `````````````` The following definitions assume that a properly constructed ``http_server`` instance has been constructed in the following manner: .. code-block:: c++ handler_type handler; http_server::options options(handler); http_server server(options.address("127.0.0.1").port("8000")); ``server.run()`` Run the HTTP Server event loop. This function can be run on multiple threads following the example: .. code-block:: c++ boost::thread t1(boost::bind(&http_server::run, &server)); boost::thread t2(boost::bind(&http_server::run, &server)); server.run(); t1.join(); t2.join(); ``server.stop()`` Stop the HTTP Server acceptor and wait for all pending requests to finish. Response Object ``````````````` The response object has its own public member functions which can be very helpful in certain simple situations. ``response = http_server::response::stock_reply(status, body)`` Code like the above should go inside the handler's ``operator()`` overload. The body parameter is an ``std::string``. The status parameter is any of the following values from the ``http_server::response`` enum ``status_type``: .. code-block:: c++ enum status_type { ok = 200, created = 201, accepted = 202, no_content = 204, multiple_choices = 300, moved_permanently = 301, moved_temporarily = 302, not_modified = 304, bad_request = 400, unauthorized = 401, forbidden = 403, not_found = 404, not_supported = 405, not_acceptable = 406, internal_server_error = 500, not_implemented = 501, bad_gateway = 502, service_unavailable = 503 }; The response object also has the following publicly accessible member values which can be directly manipulated by the handler. +------------------+----------------------+------------------------------------+ | Member Name | Type | Description | +==================+======================+====================================+ | status | ``status_type`` | The HTTP status of the response. | +------------------+----------------------+------------------------------------+ | headers | ``vector
`` | Vector of headers. [#]_ | +------------------+----------------------+------------------------------------+ | content | ``string_type`` [#]_ | The contents of the response. | +------------------+----------------------+------------------------------------+ .. [#] A header is a struct of type ``response_header``. An instance always has the members ``name`` and ``value`` both of which are of type ``string_type``. .. [#] ``string_type`` is ``boost::network::string::type``. Asynchronous Servers -------------------- The asynchronous server implementation is significantly different to the synchronous server implementation in three ways: #. **The Handler instance is invoked asynchronously**. This means the I/O thread used to handle network-related events are free to handle only the I/O related events. This enables the server to scale better as to the number of concurrent connections it can handle. #. **The Handler is able to schedule asynchronous actions on the thread pool associated with the server.** This allows handlers to perform multiple asynchronous computations that later on perform writes to the connection. #. **The Handler is able to control the (asynchronous) writes to and reads from the HTTP connection.** Because the connection is available to the Handler, that means it can write out chunks of data at a time or stream data through the connection continuously. The asynchronous server is meant to allow for better scalability in terms of the number of concurrent connections and for performing asynchronous actions within the handlers. If your application does not need to write out information asynchronously or perform potentially long computations, then the synchronous server gives a generally better performance profile than the asynchronous server. The asynchronous server implementation is available from a single user-facing template named ``async_server``. This template takes in a single template parameter which is the type of the Handler to be called once a request has been parsed from a connection. An instance of Handler is taken as a reference to the constructor similar to the synchronous server implementation. .. warning:: The asynchronous server implementation, like the synchronous server implementation, does not perform any synchronization on the calls to the Handler invocation. This means if your handler contains or maintains internal state, you are responsible for implementing your own synchronization on accesses to the internal state of the Handler. The general pattern for using the ``async_server`` template is shown below: .. code-block:: c++ struct handler; typedef boost::network::http::async_server http_server; struct handler { void operator()( http_server::request const & req, http_server::connection_ptr connection ) { // handle the request here, and use the connection to // either read more data or write data out to the client } }; API Documentation ~~~~~~~~~~~~~~~~~ The following sections assume that the following file has been included: .. code-block:: c++ #include #include And that the following typedef's have been put in place: .. code-block:: c++ struct handler_type; typedef boost::network::http::server http_server; struct handler_type { void operator()(http_server::request const & request, http_server::connection_ptr connection) { // do something here } }; Constructor ``````````` ``explicit http_server(options)`` Construct an HTTP server instance passing in a ``server_options`` instance. Public Members `````````````` The following definitions assume that a properly constructed ``http_server`` instance has been constructed in the following manner: .. code-block:: c++ handler_type handler; http_server::options options(handler); options.thread_pool(boost::make_shared(2)); http_server server(options.address("127.0.0.1").port("8000")); ``server.run()`` Run the HTTP Server event loop. This function can be run on multiple threads following the example: .. code-block:: c++ boost::thread t1(boost::bind(&http_server::run, &server)); boost::thread t2(boost::bind(&http_server::run, &server)); server.run(); t1.join(); t2.join(); ``server.stop()`` Stop the HTTP Server acceptor and wait for all pending requests to finish. Connection Object ````````````````` The connection object has its own public member functions which will be the primary means for reading from and writing to the connection. ``template write(Range range)`` The connection object exposes a function ``write`` that can be given a parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept. The write function, although it looks synchronous, starts of a series of asynchronous writes to the connection as soon as the range is serialized to appropriately sized buffers. To use this in your handler, it would look something like this: .. code-block:: c++ connection->write("Hello, world!"); std::string sample = "I have a string!"; connection->write(sample); ``template void write(Range range, Callback callback)`` The connection object also exposes a function ``write`` that can be given a parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept, as well as a Callback function that returns ``void`` and takes a ``boost::system::error_code`` as a parameter. This overload of ``write`` is useful for writing streaming applications that send out chunks of data at a time, or for writing data that may not all fit in memory right away. ``template void read(ReadCallback callback)`` The connection object has a function ``read`` which can be used to read more information from the connection. This ``read`` function takes in a callback that can be assigned to a Boost.Function_ with the signature ``void(input_range,error_code,size_t,connection_ptr)``. The following list shows what the types actually mean: * **input_range** -- ``boost::iterator_range`` : The range that denotes the data read from the connection. * **error_code** -- ``boost::system::error_code`` : The error code if there were any errors encountered from the read. * **size_t** -- ``std::size_t`` : The number of bytes transferred. * **connection_ptr** -- ``http_server::connection_ptr`` : A handle to the current connection, so that it is kept alive at the time of the read callback invocation. This interface is useful when doing reads of uploaded data that can be potentially large and may not fit in memory. The read handler is then responsible for dealing with the chunks of data available from the connection. ``void set_status(status_t new_status)`` The ``set_status`` function takes a parameter of type ``status_t`` which is an enum type nested in ``http_status::connection`` which is given in the following code listing. .. code-block:: c++ enum status_t { ok = 200 , created = 201 , accepted = 202 , no_content = 204 , multiple_choices = 300 , moved_permanently = 301 , moved_temporarily = 302 , not_modified = 304 , bad_request = 400 , unauthorized = 401 , forbidden = 403 , not_found = 404 , not_supported = 405 , not_acceptable = 406 , internal_server_error = 500 , not_implemented = 501 , bad_gateway = 502 , service_unavailable = 503 }; .. note:: You may set and re-set the status several times as long as you have not set the headers or sent data through the connection. If you do this after data has already been set, the function will throw an instance of ``std::logic_error``. ``template void set_headers(Range range)`` The ``set_headers`` function takes a Single Pass Range of ``boost::network::http::response_header`` instances and linearizes them to a buffer with at most ``BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE`` and immediately schedules an asynchronous write once that is done. The function throws an instance of ``std::logic_error`` if you try to set the headers for a connection more than once. Adding SSL support to Asynchronous Server ----------------------------------------- In order to setup SSL support for an Asynchronous Server, it is best to start from a regular Asynchronous Server (see above). Once this server is setup, SSL can be enabled by adding a Boost.Asio.Ssl.Context_ to the options. The settings that can be used are defined in the link. .. code-block:: c++ // Initialize SSL context boost::shared_ptr ctx = boost::make_shared(boost::asio::ssl::context::sslv23); ctx->set_options( boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); // Set keys ctx->set_password_callback(password_callback); ctx->use_certificate_chain_file("server.pem"); ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem); ctx->use_tmp_dh_file("dh512.pem"); handler_type handler; http_server::options options(handler); options.thread_pool(boost::make_shared(2)); http_server server(options.address("127.0.0.1").port("8442").context(ctx)); std::string password_callback(std::size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) { return std::string("test"); } .. _Boost.Range: http://www.boost.org/libs/range .. _Boost.Function: http://www.boost.org/libs/function .. _Boost.Asio.SSL.Context: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/ssl__context.html cpp-netlib-0.11.2-final/libs/network/doc/references.rst000066400000000000000000000020141256751517300227720ustar00rootroot00000000000000References ========== About :mod:`cpp-netlib` ~~~~~~~~~~~~~~~~~~~~~~~ * `BoostCon 2010 Slides`_ * `BoostCon 2010 Paper`_ Other sources ~~~~~~~~~~~~~ * `Template Metaprogramming`_: The best guide to C++ template metaprogramming. * `HTTP 1.0`_: The HTTP 1.0 specification. * `HTTP 1.1 (RFC 2616)`_: The HTTP 1.1 specification. * `URI Generic Syntax (RFC 3986)`_: Generic URI syntax specification. * `Format for Literal IPv6 Addresses in URLs (RFC 2732)`_: Literal IPv6 Addresses in URLs. .. _`BoostCon 2010 Slides`: http://www.filetolink.com/b0e89d06 .. _`BoostCon 2010 Paper`: http://github.com/downloads/mikhailberis/cpp-netlib-boostcon-paper/cpp-netlib.pdf .. _`Template Metaprogramming`: http://www.boostpro.com/mplbook/ .. _`HTTP 1.0`: http://www.w3.org/Protocols/HTTP/1.0/spec.html .. _`HTTP 1.1 (RFC 2616)`: http://www.w3.org/Protocols/rfc2616/rfc2616.html .. _`URI Generic Syntax (RFC 3986)`: http://www.ietf.org/rfc/rfc3986.txt .. _`Format for Literal IPv6 Addresses in URLs (RFC 2732)`: http://www.ietf.org/rfc/rfc2732.txt cpp-netlib-0.11.2-final/libs/network/doc/techniques.rst000066400000000000000000000004111256751517300230200ustar00rootroot00000000000000Techniques ========== The :mod:`cpp-netlib` uses several advanced techniques to achieve it's aims. This chapter describes some of those techniques. .. toctree:: :maxdepth: 1 techniques/tag_metafunctions techniques/directives techniques/polymorphism cpp-netlib-0.11.2-final/libs/network/doc/techniques/000077500000000000000000000000001256751517300222725ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/doc/techniques/directives.rst000066400000000000000000000066741256751517300252020ustar00rootroot00000000000000Directives ========== The :mod:`cpp-netlib` uses a technique for allowing message-passing semantics in a chainable fashion in the form of directives. The basic concept for directives is, in a general sense, an encapsulated transformation that can be applied to objects that abide by the directive protocol. Using the object-oriented notion of message passing, where an object accepts a message (usually a function call) we define a simple DSEL in order for the protocol to be supported by certain object types. In the :mod:`cpp-netlib` the protocol implemented is similar to that of the standard iostream formatting system: .. code-block:: c++ object << directive1(...) << directive2(...) ... << directiveN(...); In :mod:`cpp-netlib` the directives are simple function objects that take a target object as reference and returns a reference to the same object as a result. In code the directive pattern looks like the following: .. code-block:: c++ struct directive_type { template Input & operator()(Input & input) const { // do something to input return input; } }; To simplify directive creation, usually factory or generator functions are defined to return concrete objects of the directive's type. .. code-block:: c++ inline directive_type directive(...) { return directive_type(); } The trivial implementation of the directive protocol then boils down to the specialization of the shift-left operator on the target type. .. code-block:: c++ template inline target_type & operator<< (target_type & x, Directive const & f) { return f(x); } .. todo:: An example using a directive. The rationale for implementing directives include the following: * **Encapsulation** - by moving logic into the directive types the target object's interface can remain rudimentary and even hidden to the user's immediate attention. Adding this layer of indirection also allows for changing the underlying implementations while maintaining the same syntactic and semantic properties. * **Flexibility** - by allowing the creation of directives that are independent from the target object's type, generic operations can be applied based on the concept being modeled by the target type. The flexibility also afforded comes in the directive's generator function, which can also generate different concrete directive specializations based on parameters to the function. * **Extensibility** - because the directives are independent of the target object's type, new directives can be added and supported without having to change the target object at all. * **Reuse** - truly generic directives can then be used for a broad set of target object types that model the same concepts supported by the directive. Because the directives are self-contained objects, the state and other object references it keeps are only accessible to it and can be re-used in different contexts as well. Extending a system that uses directives is trivial in header-only systems because new directives are simply additive. The protocol is simple and can be applied to a broad class of situations. In a header-only library, the static nature of the wiring and chaining of the operations lends itself to compiler abuse. A deep enough nesting of the directives can lead to prolonged compilation times. cpp-netlib-0.11.2-final/libs/network/doc/techniques/polymorphism.rst000066400000000000000000000065001256751517300255670ustar00rootroot00000000000000Static and dynamic polymorphism =============================== With a header only library, you can only do so much with static polymorphism alone. There are some situations where you have to handle dynamic polymorphism because of unavoidable runtime-based decision making. Although you can deal with the base types that remain static, behavior can vary greatly which derived type should be handling the situation based on runtime values. This situation comes up in the :mod:`cpp-netlib` when we decide what kind of connection handler to use for a given HTTP URI -- whether it's plain HTTP or HTTPS. Although the HTTP semantics are the same for HTTP and HTTPS the implementation of the connection handler greatly varies on whether to use a plain TCP connection or an SSL-wrapped TCP connection. The general pattern or technique is to combine tag-based dispatch with a strategy factory, all while not requiring any externally built libraries. Doing it in a header-only library requires a little creativity and additional layers of indirection that you otherwise will not need for a library with externally built static/dynamic libraries. First we define the base type which we want to support dynamic behavior with. There's nothing special with the base type, except that it supports the tag dispatch earlier defined and has a virtual destructor. In code it looks like this: .. code-block:: c++ template struct base { virtual void foo() = 0; // make this an abstract base virtual ~base() { // do the base destructor thing here. } }; We then define a set of derived types that specialize the implementation of the ``foo`` member function. To facilitate the dispatch of the correct type based on an input, we create a strategy factory function: .. code-block:: c++ template unique_ptr > strategy(int input, Tag) { unique_ptr > ptr; switch(input) { case 0: ptr.reset(new derived0()); break; case 1: ptr.reset(new derived1()); break; // ... default: ptr.reset(0); break; } return ptr; } unique_ptr > ptr = strategy(input, default_()); // input is a runtime value The strategy factory can be a standalone function, or a static member of a factory class that is specialized by tag dispatch. This can be done like the following: .. code-block:: c++ template struct strategy; template <> struct strategy { static unique_ptr > create(int input) { unique_ptr > ptr; switch(input) { case 0: ptr.reset(new derived0()); break; case 1: ptr.reset(new derived1()); break; //... default: ptr.reset(0); break; } return ptr; } }; This approach allows the header-only libraries to define new dynamic types in subsequent versions of the library while keeping the static-dynamic bridge fluid. The only down-side to this is the possibility of derived type explosion in case there are a lot of different strategies or specializations available -- this though is not unique to static-dynamic bridging, but is also a problem with pure object oriented programming with dynamic polymorphism. cpp-netlib-0.11.2-final/libs/network/doc/techniques/tag_metafunctions.rst000066400000000000000000000130661256751517300265440ustar00rootroot00000000000000Tag metafunctions ================= Sometimes you want to vary a function or a type's behavior based on a static parameter. In the :mod:`cpp-netlib` there are a number of things you might want to change based on some such parameter -- like what the underlying string type should be and how large a buffer should be, among other things. The primary way to define this in a header-only manner is to use tag-based metafunctions. The skeleton of the approach is based on a similar technique for defining type traits. In the :mod:`cpp-netlib` however the type traits are defined on opaque tag types which serve to associate results to a family of metafunctions. Template Specialization ----------------------- To illustrate this point, let's define a tag ``default_`` which we use to denote the default implementation of a certain type ``foo``. For instance we decide that the default string type we will use for ``default_`` tagged ``foo`` specializations will be an ``std::string``. In the :mod:`cpp-netlib` this is done by defining a ``string`` metafunction type that is specialized on the tag ``default_`` whose nested ``type`` result is the type ``std::string``. In code this would translate to: .. code-block:: c++ template struct string { typedef void type; }; struct default_; template <> struct string { typedef std::string type; }; Template Metaprogramming ------------------------ Starting with version 0.7, the tag dispatch mechanism changed slightly to use Boost.MPL_. The idea is still the same, although we can get a little smarter than just using template specializations. Instead of just defining an opaque type ``default_``, we use the Boost.MPL equivalent of a vector to define which root types of properties this ``default_`` tag supports. The idea is to make the opaque type ``default_`` inherit property tags which the library supports internally as definite extension points. .. _Boost.MPL: http://www.boost.org/libs/mpl/index.html Our definition of the ``default_`` tag will then look something like the following: .. code-block:: c++ typedef mpl::vector default_tags; template struct components; typedef mpl::inherit_linearly< default_tags, mpl::inherit >::type default_; template struct components { typedef default_tags type; }; In the above listing, ``default_string`` is what we call a "root" tag which is meant to be combined with other "root" tags to form composite tags. In this case our composite tag is the tag ``default_``. There are a number of these "root" tags that :mod:`cpp-netlib` provides. These are in the namespace ``boost::network::tags`` and are defined in ``boost/network/tags.hpp``. Using this technique we change slightly our definition of the ``string`` metafunction class into this: .. code-block:: c++ template struct unsupported_tag; template struct string : mpl::if_< is_base_of< tags::default_string, Tag >, std::string, unsupported_tag > {}; Notice that we don't have the typedef for ``type`` in the body of ``string`` anymore, but we do inherit from ``mpl::if_``. Since ``mpl::if_`` is a template metafunction itself, it contains a definition of the resulting ``type`` which ``string`` inherits. You can see the real definition of the ``string`` metafunction in ``boost/network/traits/string.hpp``. Using Tags ---------- Once we have the defined tag, we can then use this in the definition of our types. In the definition of the type ``foo`` we use this type function ``string`` and pass the tag type parameter to determine what to use as the string type in the context of the type ``foo``. In code this would translate into: .. code-block:: c++ template struct foo { typedef typename string::type string_type; // .. use string_type where you need a string. }; Using this approach we can support different types of strings for different tags on the type ``foo``. In case we want to use a different type of string for the tag ``default_`` we only change the composition of the ``string_tags`` MPL vector. For example, in :mod:`cpp-netlib` there is a root tag ``default_wstring`` which causes the ``string`` metafunction to define ``std::wstring`` as the resulting type. The approach also allows for the control of the structure and features of types like ``foo`` based on the specialization of the tag. Whole type function families can be defined on tags where they are supported and ignored in cases where they are not. To illustrate let's define a new tag ``swappable``. Given the above definition of ``foo``, we want to make the ``swappable``-tagged ``foo`` define a ``swap`` function that extends the original ``default_``-tagged ``foo``. In code this would look like: .. code-block:: c++ struct swappable; template <> struct foo : foo { void swap(foo & other) { // ... } }; We also for example want to enable an ADL-reachable ``swap`` function: .. code-block:: c++ struct swappable; inline void swap(foo & left, foo & right) { left.swap(right); } Overall what the tag-based definition approach allows is for static definition of extension points that ensures type-safety and invariants. This keeps the whole extension mechanism static and yet flexible. cpp-netlib-0.11.2-final/libs/network/doc/whats_new.rst000066400000000000000000000234001256751517300226520ustar00rootroot00000000000000.. _whats_new: ************ What's New ************ :mod:`cpp-netlib` 0.11 ---------------------- v0.11.2 ~~~~~~~ * Support a source_port setting for connections made by the client per-request. * Allow using cpp-netlib without OpenSSL. * Fix build breakage for Visual Studio 2015. * Add more options for HTTP client use of SSL/TLS options/ciphers. * Made client_get_timeout_test less flaky. * Fixes to URI encoding issues with multibyte strings. * Make cpp-netlib not crash on unstable networks. * Allow parsing empty query parameters (`#499`_). * CMake build changes to simplify dependencies on cppnetlib-client-connections. * Handle EOF correctly (`#496`_). * Fix fileserver example to chunk data correctly. * Copy hostname to avoid dangling reference to a temporary request object. (`#482`_) * Catch exceptions in parse_headers to avoid propagating issues in parsing upwards. * Fix some GCC warnings on signed/unsigned comparison. * Support environment variable-based peer verification (via OpenSSL). * Support IPv6 connections. * Support certificate-based verification, and option to always verify hosts. .. _`#499`: https://github.com/cpp-netlib/cpp-netlib/issues/499 .. _`#496`: https://github.com/cpp-netlib/cpp-netlib/issues/496 .. _`#482`: https://github.com/cpp-netlib/cpp-netlib/issues/482 v0.11.1 ~~~~~~~ * Add support for request timeouts. * Build configuration fixes. * Support for Travis CI in-project config. * Make the response parser more flexible to support older/ad-hoc servers that don't have standard format responses. * Fix some instability in the client destructor. * MSVC 2010 specific fixes. v0.11.0 ~~~~~~~ * Fix thread leak in DNS resolution failure (`#245`_) * Remove unsupported `client_fwd.hpp` header (`#277`_) * Remove support for header-only usage (`#129`_) -- this means that the BOOST_NETWORK_NO_LIB option is no longer actually supported. * Deprecate Synchronous Client implementations (`#279`_) * Support streaming body chunks for PUT/POST client requests (`#27`_) * Fix non-case-sensitive header parsing for some client tags (`#313`_) * Remove unsupported Jamfiles from the whole project (`#316`_) * Add ``make install`` for Linux and OS X (`#285`_) * Fix incorrect Body processing (`#69`_) * Support chunked transfer encoding from HTTP responses (`#86`_) * Make OS X Clang builds use C++11 and libc++. * Update Boost requirement to 1.54.0. * Experimental Base64 encoding/decoding library (`#287`_) * *Known test failure:* OS X Xcode Clang 5.0 + Boost 1.54.0 + libc++ don't play well with Boost.Serialization issues, mitigate test breakage but ``cpp-netlib-utils_base64_test`` still fails in this platform. (`#287`_) * Provide a client option to always validate peers for HTTPS requests made by the client. (`#349`_) * Back-port fix for `#163`_ for improved URI parsing. * Added support for client-side certificates and private keys (`#361`_). .. _`#129`: https://github.com/cpp-netlib/cpp-netlib/issues/129 .. _`#163`: https://github.com/cpp-netlib/cpp-netlib/issues/163 .. _`#245`: https://github.com/cpp-netlib/cpp-netlib/issues/245 .. _`#277`: https://github.com/cpp-netlib/cpp-netlib/issues/277 .. _`#279`: https://github.com/cpp-netlib/cpp-netlib/issues/279 .. _`#27`: https://github.com/cpp-netlib/cpp-netlib/issues/27 .. _`#285`: https://github.com/cpp-netlib/cpp-netlib/issues/285 .. _`#287`: https://github.com/cpp-netlib/cpp-netlib/issues/287 .. _`#313`: https://github.com/cpp-netlib/cpp-netlib/issues/313 .. _`#316`: https://github.com/cpp-netlib/cpp-netlib/issues/316 .. _`#349`: https://github.com/cpp-netlib/cpp-netlib/issues/349 .. _`#69`: https://github.com/cpp-netlib/cpp-netlib/issues/69 .. _`#86`: https://github.com/cpp-netlib/cpp-netlib/issues/86 .. _`#361`: https://github.com/cpp-netlib/cpp-netlib/pull/361 :mod:`cpp-netlib` 0.10 ---------------------- v0.10.1 ~~~~~~~ * Documentation updates (`#182`_, `#265`_, `#194`_, `#233`_, `#255`_) * Fix issue with async server inadvertently stopping from listening when accepting a connection fails. (`#172`_) * Allow overriding and ultimately removing defaulted headers from HTTP requests. (`#263`_) * Add `-Wall` to the base rule for GCC builds. (`#264`_) * Make the server implementation throw on startup errors. (`#166`_) .. _`#182`: https://github.com/cpp-netlib/cpp-netlib/issues/182 .. _`#265`: https://github.com/cpp-netlib/cpp-netlib/issues/265 .. _`#194`: https://github.com/cpp-netlib/cpp-netlib/issues/194 .. _`#172`: https://github.com/cpp-netlib/cpp-netlib/issues/172 .. _`#263`: https://github.com/cpp-netlib/cpp-netlib/issues/263 .. _`#233`: https://github.com/cpp-netlib/cpp-netlib/issues/233 .. _`#264`: https://github.com/cpp-netlib/cpp-netlib/issues/264 .. _`#255`: https://github.com/cpp-netlib/cpp-netlib/issues/255 .. _`#166`: https://github.com/cpp-netlib/cpp-netlib/issues/166 v0.10.0 ~~~~~~~ * Added support for more HTTP status codes (206, 408, 412, 416, 507). * Refactored the parser for chunked encoding. * Fixed parsing chunked encoding if the response body has ``CLRFCLRF``. * Added librt dependency on Linux. * Check the callback in the asynchronous client before calling it. * Fixed issues `#110`_, `#168`_, `#213`_. .. _`#110`: https://github.com/cpp-netlib/cpp-netlib/issues/110 .. _`#168`: https://github.com/cpp-netlib/cpp-netlib/issues/168 .. _`#213`: https://github.com/cpp-netlib/cpp-netlib/issues/213 :mod:`cpp-netlib` 0.9 --------------------- v0.9.5 ~~~~~~ * Removed dependency on Boost.Parameter from HTTP client and server. * Fixed for Clang error on Twitter example. * Added source port to the request (HTTP server). * Updated CMake config for MSVC 2010/2012. * Now support chunked content encoding in client response parsing. * Fixed bug with client not invoking callback when a request fails. v0.9.4 ~~~~~~ * Lots of URI fixes. * Fixed async_server's request handler so it doesn't make copies of the supplied handler. * Fix for issue `#73`_ regarding SSL connections ending in short read errors. * Final C++03-only release. .. _`#73`: https://github.com/cpp-netlib/cpp-netlib/issues/73 v0.9.3 ~~~~~~ * URI, HTTP client and HTTP server are now built as static libraries (``libcppnetlib-uri.a``, ``libcppnetlib-client-connections.a`` and ``libcppnetlib-server-parsers.a`` on Linux and ``cppnetlib-uri.lib``, ``cppnetlib-client-connections.lib`` and ``cppnetlib-server-parsers.lib`` on Windows). * Updated URI parser. * A new URI builder. * URI support for IPv6 RFC 2732. * Fixed issues `#67`_, `#72`_, `#78`_, `#79`_, `#80`_, `#81`_, `#82`_, `#83`_. * New examples for the HTTP client, including an Atom feed, an RSS feed and a very simple client that uses the Twitter Search API. .. _`#67`: https://github.com/cpp-netlib/cpp-netlib/issues/67 .. _`#72`: https://github.com/cpp-netlib/cpp-netlib/issues/72 .. _`#78`: https://github.com/cpp-netlib/cpp-netlib/issues/78 .. _`#79`: https://github.com/cpp-netlib/cpp-netlib/issues/79 .. _`#80`: https://github.com/cpp-netlib/cpp-netlib/issues/80 .. _`#81`: https://github.com/cpp-netlib/cpp-netlib/issues/81 .. _`#82`: https://github.com/cpp-netlib/cpp-netlib/issues/82 .. _`#83`: https://github.com/cpp-netlib/cpp-netlib/issues/83 v0.9.2 ~~~~~~ * Critial bug fixes to v0.9.1. v0.9.1 ~~~~~~ * Introduced macro ``BOOST_NETWORK_DEFAULT_TAG`` to allow for programmatically defining the default flag to use throughout the compilation unit. * Support for streaming body handlers when performing HTTP client operations. See documentation for HTTP client interface for more information. * Numerous bug fixes from v0.9.0. * Google, Inc. contributions. v0.9.0 ~~~~~~ * **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use :mod:`cpp-netlib` in header-only mode, users must define the preprocessor macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only. * Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` which makes the default HTTP client use ``tags::http_async_8bit_udp_resolve`` as the tag. * Fix issue #40: Write the status line and headers in a single buffer write instead of two writes. * More consistent message API for client and server messages (request and response objects). * Refactoring of internal implementations to allow better separation of concerns and more manageable coding/documentation. * Client and server constructors that support Boost.Parameter named parameters. * Client and server constructors now take in an optional reference to a Boost.Asio ``io_service`` to use internally. * Documentation updates to reflect new APIs. :mod:`cpp-netlib` 0.8 --------------------- * Updates to URI unit tests and documentation. * More documentation, covering the HTTP Client and HTTP Server APIs * Asynchronous HTTP Server that now supports running request handlers on a different thread pool. * An initial thread pool implementation, using Boost.Asio underneath. * Adding a ready(...) wrapper to check whether a response object returned by the asynchronous client in 0.7 already has all the parts available. * Some attempts at lowering compile time costs. :mod:`cpp-netlib` 0.7 --------------------- * Radical documentation overhaul * Asynchronous HTTP client * Tag dispatch overhaul, using Boost.MPL * HTTP Client Facade refactoring * Bug fixes for HTTP 1.1 response parsing * Minimized code repetition with some header macro's * Configurable HTTPS support in the library with ``BOOST_NETWORK_ENABLE_HTTPS`` :mod:`cpp-netlib` 0.6 --------------------- * Many fixes for MSVC compiler :mod:`cpp-netlib` 0.5 --------------------- * An embeddable HTTP 1.1 server * An HTTP 1.1 client upgraded to support HTTPS * An updated URI parser implementation * An asynchronous HTTP 1.1 client * An HTTP 1.1 client that supports streaming function handlers cpp-netlib-0.11.2-final/libs/network/example/000077500000000000000000000000001256751517300210105ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/CMakeLists.txt000066400000000000000000000142031256751517300235500ustar00rootroot00000000000000# Copyright (c) Dean Michael Berris 2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) if (OPENSSL_FOUND) include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) add_executable(atom_reader atom/atom.cpp atom/main.cpp) add_executable(rss_reader rss/rss.cpp rss/main.cpp) add_executable(twitter_search twitter/search.cpp) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(hello_world_client http/hello_world_client.cpp) add_executable(hello_world_async_server_with_work_queue http/hello_world_async_server_with_work_queue.cpp) add_executable(trivial_google trivial_google.cpp) if (UNIX) add_executable(fileserver http/fileserver.cpp) endif (UNIX) add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) add_dependencies(atom_reader cppnetlib-uri cppnetlib-client-connections) add_dependencies(rss_reader cppnetlib-uri cppnetlib-client-connections) add_dependencies(twitter_search cppnetlib-uri cppnetlib-client-connections) add_dependencies(trivial_google cppnetlib-uri cppnetlib-client-connections) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY}) set(BOOST_SERVER_LIBS ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY}) target_link_libraries(http_client ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(simple_wget ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(atom_reader ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(rss_reader ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(twitter_search ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(trivial_google ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(hello_world_server ${BOOST_SERVER_LIBS} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(hello_world_client ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(hello_world_async_server_with_work_queue ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections cppnetlib-server-parsers) if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) target_link_libraries(rss_reader ${OPENSSL_LIBRARIES}) target_link_libraries(twitter_search ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_client ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_async_server_with_work_queue ${OPENSSL_LIBRARIES}) target_link_libraries(trivial_google ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(http_client ws2_32) target_link_libraries(simple_wget ws2_32) target_link_libraries(atom_reader ws2_32) target_link_libraries(rss_reader ws2_32) target_link_libraries(twitter_search ws2_32) target_link_libraries(hello_world_server ws2_32 wsock32) target_link_libraries(hello_world_client ws2_32) target_link_libraries(hello_world_async_server_with_work_queue ws2_32 wsock32) target_link_libraries(trivial_google ws2_32) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(http_client rt) target_link_libraries(simple_wget rt) target_link_libraries(atom_reader rt) target_link_libraries(rss_reader rt) target_link_libraries(twitter_search rt) target_link_libraries(hello_world_server rt) target_link_libraries(hello_world_client rt) target_link_libraries(hello_world_async_server_with_work_queue rt) target_link_libraries(trivial_google rt) endif() if (UNIX) target_link_libraries(fileserver ${BOOST_SERVER_LIBS} ${Boost_FILESYSTEM_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(fileserver rt) endif() if (OPENSSL_FOUND) target_link_libraries(fileserver ${OPENSSL_LIBRARIES}) endif(OPENSSL_FOUND) endif (UNIX) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(rss_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(twitter_search PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(trivial_google PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_async_server_with_work_queue PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (UNIX) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif (UNIX) cpp-netlib-0.11.2-final/libs/network/example/atom/000077500000000000000000000000001256751517300217505ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/atom/atom.cpp000066400000000000000000000053301256751517300234150ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "atom.hpp" #include "../rapidxml/rapidxml.hpp" #include #include namespace boost { namespace network { namespace atom { feed::feed(const http::client::response &response) { std::string response_body = body(response); rapidxml::xml_document<> doc; doc.parse<0>(const_cast(response_body.c_str())); rapidxml::xml_node<> *feed = doc.first_node("feed"); if (!feed) { throw std::runtime_error("Invalid atom feed."); } rapidxml::xml_node<> *title = feed->first_node("title"); if (title) { title_ = title->first_node()->value(); } rapidxml::xml_node<> *subtitle = feed->first_node("subtitle"); if (subtitle) { subtitle_ = subtitle->first_node()->value(); } rapidxml::xml_node<> *id = feed->first_node("id"); if (id) { id_ = id->first_node()->value(); } rapidxml::xml_node<> *updated = feed->first_node("updated"); if (updated) { updated_ = updated->first_node()->value(); } rapidxml::xml_node<> *author = feed->first_node("author"); if (author) { rapidxml::xml_node<> *name = author->first_node("name"); rapidxml::xml_node<> *email = author->first_node("email"); if (name && email) { author_ = atom::author(name->first_node()->value(), email->first_node()->value()); } else if (name) { author_ = atom::author(name->first_node()->value()); } } rapidxml::xml_node<> *entry = feed->first_node("entry"); while (entry) { entries_.push_back(atom::entry()); rapidxml::xml_node<> *title = entry->first_node("title"); if (title) { entries_.back().set_title(title->first_node()->value()); } rapidxml::xml_node<> *id = entry->first_node("id"); if (id) { entries_.back().set_id(id->first_node()->value()); } rapidxml::xml_node<> *published = entry->first_node("published"); if (published) { entries_.back().set_published(published->first_node()->value()); } rapidxml::xml_node<> *updated = entry->first_node("updated"); if (updated) { entries_.back().set_updated(updated->first_node()->value()); } rapidxml::xml_node<> *summary = entry->first_node("summary"); if (summary) { entries_.back().set_summary(summary->first_node()->value()); } rapidxml::xml_node<> *content = entry->first_node("content"); if (content) { entries_.back().set_content(content->first_node()->value()); } entry = entry->next_sibling(); } } } // namespace atom } // namespace network } // namespace boost cpp-netlib-0.11.2-final/libs/network/example/atom/atom.hpp000066400000000000000000000050671256751517300234310ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef ___ATOM_INC__ #define ___ATOM_INC__ #include #include #include namespace boost { namespace network { namespace atom { class entry { public: void set_title(const std::string &title) { title_ = title; } std::string title() const { return title_; } void set_id(const std::string &id) { id_ = id; } std::string id() const { return id_; } void set_published(const std::string &published) { published_ = published; } std::string published() const { return published_; } void set_updated(const std::string &updated) { updated_ = updated; } std::string updated() const { return updated_; } void set_summary(const std::string &summary) { summary_ = summary; } std::string summary() const { return summary_; } void set_content(const std::string &content) { content_ = content; } std::string content() const { return content_; } private: std::string title_; std::string id_; std::string published_; std::string updated_; std::string summary_; std::string content_; }; class author { public: author() {} author(const std::string &name) : name_(name) {} author(const std::string &name, const std::string &email) : name_(name), email_(email) {} std::string name() const { return name_; } std::string email() const { return email_; } private: std::string name_; std::string email_; }; class feed { public: typedef entry value_type; typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; feed(const http::client::response &response); std::string title() const { return title_; } std::string subtitle() const { return subtitle_; } std::string id() const { return id_; } std::string updated() const { return updated_; } atom::author author() const { return author_; } unsigned int entry_count() const { return entries_.size(); } iterator begin() { return entries_.begin(); } iterator end() { return entries_.end(); } const_iterator begin() const { return entries_.begin(); } const_iterator end() const { return entries_.end(); } private: std::string title_; std::string subtitle_; std::string id_; std::string updated_; atom::author author_; std::vector entries_; }; } // namespace atom } // namespace network } // namespace boost #endif // ___ATOM_INC__ cpp-netlib-0.11.2-final/libs/network/example/atom/main.cpp000066400000000000000000000020661256751517300234040ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "atom.hpp" #include #include #include int main(int argc, char *argv[]) { using namespace boost::network; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } try { http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); atom::feed feed(response); std::cout << "Feed: " << feed.title() << " (" << feed.subtitle() << ")" << std::endl; BOOST_FOREACH(const atom::entry & entry, feed) { std::cout << entry.title() << " (" << entry.published() << ")" << std::endl; } } catch (std::exception &e) { std::cerr << e.what() << std::endl; } return 0; } cpp-netlib-0.11.2-final/libs/network/example/http/000077500000000000000000000000001256751517300217675ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/http/fileserver.cpp000066400000000000000000000155431256751517300246510ustar00rootroot00000000000000// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include namespace http = boost::network::http; namespace utils = boost::network::utils; struct file_server; typedef http::async_server server; struct file_cache { typedef std::map > region_map; typedef std::map > meta_map; std::string doc_root_; region_map regions; meta_map file_headers; boost::shared_mutex cache_mutex; explicit file_cache(std::string const &doc_root) : doc_root_(doc_root) {} ~file_cache() throw() { BOOST_FOREACH(region_map::value_type const & region, regions) { munmap(region.second.first, region.second.second); } } bool has(std::string const &path) { boost::shared_lock lock(cache_mutex); return regions.find(doc_root_ + path) != regions.end(); } bool add(std::string const &path) { boost::upgrade_lock lock(cache_mutex); std::string real_filename = doc_root_ + path; if (regions.find(real_filename) != regions.end()) return true; #ifdef O_NOATIME int fd = open(real_filename.c_str(), O_RDONLY | O_NOATIME | O_NONBLOCK); #else int fd = open(real_filename.c_str(), O_RDONLY | O_NONBLOCK); #endif if (fd == -1) return false; std::size_t size = lseek(fd, 0, SEEK_END); void *region = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); if (region == MAP_FAILED) { close(fd); return false; } boost::upgrade_to_unique_lock unique_lock(lock); regions.insert(std::make_pair(real_filename, std::make_pair(region, size))); static server::response_header common_headers[] = { {"Connection", "close"}, {"Content-Type", "x-application/octet-stream"}, {"Content-Length", "0"}}; std::vector headers(common_headers, common_headers + 3); headers[2].value = boost::lexical_cast(size); file_headers.insert(std::make_pair(real_filename, headers)); return true; } std::pair get(std::string const &path) { boost::shared_lock lock(cache_mutex); region_map::const_iterator region = regions.find(doc_root_ + path); if (region != regions.end()) return region->second; else return std::pair(0, 0); } boost::iterator_range::iterator> meta( std::string const &path) { boost::shared_lock lock(cache_mutex); static std::vector empty_vector; meta_map::iterator headers = file_headers.find(doc_root_ + path); if (headers != file_headers.end()) { std::vector::iterator begin = headers->second .begin(), end = headers->second.end(); return boost::make_iterator_range(begin, end); } else return boost::make_iterator_range(empty_vector); } }; struct connection_handler : boost::enable_shared_from_this { explicit connection_handler(file_cache &cache) : file_cache_(cache) {} void operator()(std::string const &path, server::connection_ptr connection, bool serve_body) { bool ok = file_cache_.has(path); if (!ok) ok = file_cache_.add(path); if (ok) { send_headers(file_cache_.meta(path), connection); if (serve_body) send_file(file_cache_.get(path), 0, connection); } else { not_found(path, connection); } } void not_found(std::string const &path, server::connection_ptr connection) { static server::response_header headers[] = {{"Connection", "close"}, {"Content-Type", "text/plain"}}; connection->set_status(server::connection::not_found); connection->set_headers(boost::make_iterator_range(headers, headers + 2)); connection->write("File Not Found!"); } template void send_headers(Range const &headers, server::connection_ptr connection) { connection->set_status(server::connection::ok); connection->set_headers(headers); } void send_file(std::pair mmaped_region, off_t offset, server::connection_ptr connection) { // chunk it up page by page std::size_t adjusted_offset = offset + 4096; off_t rightmost_bound = std::min(mmaped_region.second, adjusted_offset); connection->write( boost::asio::const_buffers_1( static_cast(mmaped_region.first) + offset, rightmost_bound - offset), boost::bind(&connection_handler::handle_chunk, connection_handler::shared_from_this(), mmaped_region, rightmost_bound, connection, _1)); } void handle_chunk(std::pair mmaped_region, off_t offset, server::connection_ptr connection, boost::system::error_code const &ec) { assert(offset>=0); if (!ec && static_cast(offset) < mmaped_region.second) send_file(mmaped_region, offset, connection); } file_cache &file_cache_; }; struct file_server { explicit file_server(file_cache &cache) : cache_(cache) {} void operator()(server::request const &request, server::connection_ptr connection) { if (request.method == "HEAD") { boost::shared_ptr h(new connection_handler(cache_)); (*h)(request.destination, connection, false); } else if (request.method == "GET") { boost::shared_ptr h(new connection_handler(cache_)); (*h)(request.destination, connection, true); } else { static server::response_header error_headers[] = { {"Connection", "close"}}; connection->set_status(server::connection::not_supported); connection->set_headers( boost::make_iterator_range(error_headers, error_headers + 1)); connection->write("Method not supported."); } } file_cache &cache_; }; int main(int argc, char *argv[]) { file_cache cache("."); file_server handler(cache); server::options options(handler); server instance(options.thread_pool(boost::make_shared(4)) .address("0.0.0.0") .port("8000")); instance.run(); return 0; } cpp-netlib-0.11.2-final/libs/network/example/http/hello_world_async_server_with_work_queue.cpp000066400000000000000000000106771256751517300331040ustar00rootroot00000000000000/* * sample application to show the usage of work queues along with async http *server * * (C) Copyright Dino Korah 2013. * Distributed under the Boost Software License, Version 1.0. (See copy at * http://www.boost.org/LICENSE_1_0.txt) */ #include #include #include #include #include #include #include #include #include #define Log(line) \ do { \ std::cout << line << std::endl; \ } while (false) struct handler; typedef boost::network::http::async_server server; /** * request + connection encapsulation (work item) */ struct request_data { const server::request req; server::connection_ptr conn; typedef boost::shared_ptr pointer; request_data(server::request const& req, const server::connection_ptr& conn) : req(req), conn(conn) {} }; /** * A basic work queue */ struct work_queue { typedef std::list list; list requests; boost::mutex mutex; inline void put(const request_data::pointer& p_rd) { boost::unique_lock lock(mutex); requests.push_back(p_rd); (void)lock; } inline request_data::pointer get() { boost::unique_lock lock(mutex); request_data::pointer p_ret; if (!requests.empty()) { p_ret = requests.front(); requests.pop_front(); } (void)lock; return p_ret; } }; struct handler { work_queue& queue; handler(work_queue& queue) : queue(queue) {} /** * Feed the work queue * * @param req * @param conn */ void operator()(server::request const& req, const server::connection_ptr& conn) { queue.put(boost::make_shared(req, conn)); } }; /** * Clean shutdown signal handler * * @param error * @param signal * @param p_server_instance */ void shut_me_down(const boost::system::error_code& error, int signal, boost::shared_ptr p_server_instance) { if (!error) p_server_instance->stop(); } /** * Process request; worker (thread) * * @param queue */ void process_request(work_queue& queue) { while (!boost::this_thread::interruption_requested()) { request_data::pointer p_req(queue.get()); if (p_req) { // some heavy work! boost::this_thread::sleep(boost::posix_time::seconds(10)); p_req->conn->set_status(server::connection::ok); p_req->conn->write("Hello, world!"); } boost::this_thread::sleep(boost::posix_time::microseconds(1000)); } } int main(void) try { // the thread group boost::shared_ptr p_threads( boost::make_shared()); // setup asio::io_service boost::shared_ptr p_io_service( boost::make_shared()); boost::shared_ptr p_work( boost::make_shared( boost::ref(*p_io_service))); // io_service threads { int n_threads = 5; while (0 < n_threads--) { p_threads->create_thread( boost::bind(&boost::asio::io_service::run, p_io_service)); } } // the shared work queue work_queue queue; // worker threads that will process the request; off the queue { int n_threads = 5; while (0 < n_threads--) { p_threads->create_thread(boost::bind(process_request, boost::ref(queue))); } } // setup the async server handler request_handler(queue); boost::shared_ptr p_server_instance(boost::make_shared( server::options(request_handler) .address("0.0.0.0") .port("8800") .io_service(p_io_service) .reuse_address(true) .thread_pool(boost::make_shared( 2, p_io_service, p_threads)))); // setup clean shutdown boost::asio::signal_set signals(*p_io_service, SIGINT, SIGTERM); signals.async_wait(boost::bind(shut_me_down, _1, _2, p_server_instance)); // run the async server p_server_instance->run(); // we are stopped - shutting down p_threads->interrupt_all(); p_work.reset(); p_io_service->stop(); p_threads->join_all(); Log("Terminated normally"); exit(EXIT_SUCCESS); } catch (const std::exception& e) { Log("Abnormal termination - exception:" << e.what()); exit(EXIT_FAILURE); } cpp-netlib-0.11.2-final/libs/network/example/http/hello_world_client.cpp000066400000000000000000000023161256751517300263450ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //[ hello_world_client_main /*` This is a part of the 'Hello World' example. We create a client object and make a single HTTP request. If we use make this request to the `hello_world_server`, then the output is simply "Hello, World!". */ #include #include namespace http = boost::network::http; int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " url" << std::endl; return 1; } try { /*<< Creates the client. >>*/ http::client client; /*<< Creates a request using a URI supplied on the command line. >>*/ http::client::request request(argv[1]); /*<< Gets a response from the HTTP server. >>*/ http::client::response response = client.get(request); /*<< Prints the response body to the console. >>*/ std::cout << body(response) << std::endl; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } //] cpp-netlib-0.11.2-final/libs/network/example/http/hello_world_server.cpp000066400000000000000000000035301256751517300263740ustar00rootroot00000000000000// Copyright 2009 (c) Tarro, Inc. // Copyright 2009 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // //[ hello_world_server_main /*` This is a part of the 'Hello World' example. It's used to demonstrate how easy it is to set up an HTTP server. All we do in this example is create a request handler and run the server. */ #include #include namespace http = boost::network::http; /*<< Defines the server. >>*/ struct hello_world; typedef http::server server; /*<< Defines the request handler. It's a class that defines two functions, `operator()` and `log()` >>*/ struct hello_world { /*<< This is the function that handles the incoming request. >>*/ void operator()(server::request const &request, server::response &response) { server::string_type ip = source(request); unsigned int port = request.source_port; std::ostringstream data; data << "Hello, " << ip << ':' << port << '!'; response = server::response::stock_reply(server::response::ok, data.str()); } /*<< It's necessary to define a log function, but it's ignored in this example. >>*/ void log(...) { // do nothing } }; int main(int argc, char *argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; } try { /*<< Creates the request handler. >>*/ hello_world handler; /*<< Creates the server. >>*/ server::options options(handler); server server_(options.address(argv[1]).port(argv[2])); /*<< Runs the server. >>*/ server_.run(); } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } //] cpp-netlib-0.11.2-final/libs/network/example/http/one_liner.cpp000066400000000000000000000011321256751517300244420ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //[ http_one_liner_main /*` */ #include using namespace std; using namespace boost::network; using namespace boost::network::http; int main(int argc, const char *argv[]) { /*<< The client sends an HTTP request to the server, and the output is printed to the console. >>*/ cout << body(client().get(client::request("http://www.boost.org/"))); return 0; } cpp-netlib-0.11.2-final/libs/network/example/http/ssl/000077500000000000000000000000001256751517300225705ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/http/ssl/dh512.pem000066400000000000000000000007221256751517300241170ustar00rootroot00000000000000Diffie-Hellman-Parameters: (512 bit) prime: 00:f8:57:8f:79:09:08:95:c9:0a:74:2c:85:b5:75: ff:07:67:c0:d2:94:4f:a2:45:77:7e:e1:f4:b6:86: 60:9a:33:80:7b:31:75:f3:fc:8e:c3:0b:d0:8d:77: a4:ed:3a:e8:e4:35:69:3e:ce:63:49:26:a4:64:38: 55:41:51:de:13 generator: 5 (0x5) -----BEGIN DH PARAMETERS----- MEYCQQD4V495CQiVyQp0LIW1df8HZ8DSlE+iRXd+4fS2hmCaM4B7MXXz/I7DC9CN d6TtOujkNWk+zmNJJqRkOFVBUd4TAgEF -----END DH PARAMETERS----- cpp-netlib-0.11.2-final/libs/network/example/http/ssl/server.pem000066400000000000000000000061321256751517300246030ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,0ED70FE151E3399B +0JpEbgYMyIdEE7yKdosnNzzwGffSe6UIOf/8RgWg5N1f6obqYVRPaO53R1Fdhx2 08q5acaNNCZcoCs1X0s0F/dr4L5XOorz2W5qUKnlDiZqBVBfpW8vIKMiZxOBePO7 /h4LGtuX843k5sCmXnONtDJrpklsds0/vvZbuln6VHNf3mCWdLc8d5yJq/nPUKSm hBd8uXPF0VUSSmTre2P0pTACz2WWI7N2uWKJqBJgGbqTfR5ciufXVR/n9leICjWM LiipPMdp4ZNGDQcP3eW7/pSgxGzGvxP9e1vTEkmv0/fRGgClOdQbs+uEyDemOA+V KHJYGhdhSCDM4VJQTO40dDhsn0glp9IjchYrxjI6jyziG1Jg7YMhoeQBMYm1zSsY vqB0i7gtjVBKzltWN9fNvZ1kOJWhOsHuPocP4L4sqaQEqWCMtcKnm8ECGYXtu8E2 QmDokiWqO1+MORf+naU0nOTtnXSpsysBn1ns+8TeUzaLAy8Dd/mhX2+SWnwGs0RI VEYP+mef96SnqOKy2mDl/uzwcKUdKw4wnXrb2s8039gXBDZL09YlJxu/b/h67Dzn LSRft4JjdojTmT0Ji4eJFiew9L3bbbUyIhA9M/cdoNEnXMmOcO+XDMxemaaX4rLf nmEUcz0xpe8CVqTgx/TuOv06PX/iLyCYPnz5nczeVIw0a1/9g4WRghtoO/ezGJia jpJRmXI7Mcw4z4GgW1AbVEeIPSXQD6sqnuNcY4h/62XkVI29FjsVgU1ZRx5fu68L EIPuEri087Eep1NdRHOWwN03ppRdNxQQqB4uMNL2ruX3LzRKa0p7OQ3iL7e2V6el 2srv/5AYtFCq/adukhNcpU/otSZ5Re5B6C1zLAEUSKcgYHjCOUluq8HnCijnVCMh pEQPaSM0P36DlNFjAWFlK8/N80LOfiYekLyZLbHjczSOS3EyVyvuF3pbtSHzpgtF W4EJD8siMTXcE5hL8Ws1FwWHfviAq/mI4NUcNNz6S/4IcHS6teQOE5/uFcicJxXl 2wgZgYzBUeQlSqyI6XKoyfdJXducbLQqSWLEHL++Ek0ZaUKOiF+iGKPE0azKwMCc QumPY+R2BhJbuiTQE36hBpte//XPQS5dWwXW5RTJm8ARNl1vNR/DESfhWX+wmKqx 2UBDRoEBa5HvrU82tWeGgm9CvTg6EOSNkap/BSdd3np631NnVm1tYz/flQvw4+5t AH0X9C1QsGFwP6y/pAZ+YB+U65iN1UE3D3U1pC5JL+56ETc3GsPKnsWhAftIMm4r l7zJ4BsrvfVnRaZFH4W+ITGy5q7iLD6Tuhpq574DxCINHtiENr00ZfPw08pMpvjG 5qhuE7Vgx5MGcVhUkz+Dtsm7bDRNsRxGAO5MSiIl70oahB5q247HF2ZElVT6+LbU rQlIL4OdTdSXplW84NcoLTRy1HmLPf8B0Dt5f9Es0fAeWMiOmrrzM+spOgGXQhwv VnqQrDeSDk6TOjN5z+BuwFfR7kImO+/As9NnG8D0l0PCRMW79mED2iOTnyHT8g8b JLOjK/u2RxXFtbRwhERl4pei3NHfX4yXz2mcFjFLEOKin909WqObwedMsOUYoiN9 -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIJAI84QTgzQ+NXMA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV BAYTAkJFMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQKEwljcHBuZXRsaWIx DDAKBgNVBAsTA3NzbDEPMA0GA1UEAxMGc2VydmVyMB4XDTE0MDUyMTA4MzI1OFoX DTI0MDUxODA4MzI1OFowVTELMAkGA1UEBhMCQkUxEzARBgNVBAgTClNvbWUtU3Rh dGUxEjAQBgNVBAoTCWNwcG5ldGxpYjEMMAoGA1UECxMDc3NsMQ8wDQYDVQQDEwZz ZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZdnFuC9w3Jmdh nQkeCD3rJ3LbmopRJkBFeAdHXvF2zPedsCjQ2J9XNcrGoejQuWNzEfmhs8pPSve3 +Hn5AmqByGzN6aylJnD4qZZqpV1JrWvhReswLJktUTKtu+gh2a3gZjvXAdkGi0QX LoXyAFuhILmivE9bQB6unUpMhGiAfX9AxDINgBt/+oi2V8bkXdJl45BNUY9IqgaJ 9WeDC37DmORb/IDHjmancIMyirDG2SBBGOVv/wuI0a/QUmjtBKUMEiX8PtyKSORA PnOd2Fe0LL70thBD1WtlMNoU3upIrlLUE0F4bb+Ibn+iuSyu6dWp7rr9kR3uigQ6 gspTVX4RAgMBAAGjgbgwgbUwHQYDVR0OBBYEFHZpVctJQmv6ixP7PmHcFUa+7+Dy MIGFBgNVHSMEfjB8gBR2aVXLSUJr+osT+z5h3BVGvu/g8qFZpFcwVTELMAkGA1UE BhMCQkUxEzARBgNVBAgTClNvbWUtU3RhdGUxEjAQBgNVBAoTCWNwcG5ldGxpYjEM MAoGA1UECxMDc3NsMQ8wDQYDVQQDEwZzZXJ2ZXKCCQCPOEE4M0PjVzAMBgNVHRME BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCd70N4MzxI7jKdyFXNQtHLh74hALd5 p2PconV+3dE3yge88Z9IkgIx8MtVl6jm7dlggwJLGTBUD5fI0iL+KWqLl7/QxbwS 82J28ScsXlEf7pygowEsUYPM8j6O42JhIGQqMWOnmqnBVDxszHvYkO12/JupbEeK p5RYS3GkyxQm5MmX0pX0H6wdfCkOdSZrHaXTx2wq2lKeQgN3mECUH51jXzB1G3nI y1dCMD+AF3eUqS2UxgPbF14U6V2vsk4DvbgyzjYFjF+ttFdnIgGwAJJWet+orhW/ k+h3ZaviXhOyqjpXHXGkVUj+/AvKWArjl7D6Xh03iUp0xt1Bn28CxQ90 -----END CERTIFICATE----- cpp-netlib-0.11.2-final/libs/network/example/http/ssl/ssl_server.cpp000066400000000000000000000062241256751517300254670ustar00rootroot00000000000000/* * Sample application based loosely on existing async server sample to *demonstrate ssl * * Requires openssl lib to run (https://www.openssl.org/) * * (C) Copyright Jelle Van den Driessche 2014. * * Distributed under the Boost Software License, Version 1.0. (See copy at * http://www.boost.org/LICENSE_1_0.txt) */ #include #include #include #include #include #include struct handler; typedef boost::network::http::async_server server; std::string password_callback( std::size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) { return std::string("test"); } /** * request + connection encapsulation (work item) */ struct request_data { const server::request req; server::connection_ptr conn; typedef boost::shared_ptr pointer; request_data(server::request const& req, const server::connection_ptr& conn) : req(req), conn(conn) {} }; struct handler { void operator()(server::request const& req, const server::connection_ptr& conn) { conn->set_status(server::connection::ok); conn->write(std::string("Hello World!!")); } }; /** * Clean shutdown signal handler * * @param error * @param signal * @param p_server_instance */ void shut_me_down(const boost::system::error_code& error, int signal, boost::shared_ptr p_server_instance) { if (!error) p_server_instance->stop(); } int main(void) try { // setup asio::io_service boost::shared_ptr p_io_service( boost::make_shared()); // Initialize SSL context boost::shared_ptr ctx = boost::make_shared( boost::asio::ssl::context::sslv23); ctx->set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); // Set keys ctx->set_password_callback(password_callback); ctx->use_certificate_chain_file("server.pem"); ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem); ctx->use_tmp_dh_file("dh512.pem"); // setup the async server handler request_handler; boost::shared_ptr p_server_instance(boost::make_shared( server::options(request_handler) .address("0.0.0.0") .port("8442") .io_service(p_io_service) .reuse_address(true) .thread_pool( boost::make_shared(2)) .context(ctx))); // setup clean shutdown boost::asio::signal_set signals(*p_io_service, SIGINT, SIGTERM); signals.async_wait(boost::bind(shut_me_down, _1, _2, p_server_instance)); // run the async server p_server_instance->run(); // we are stopped - shutting down p_io_service->stop(); std::cout << "Terminated normally" << std::endl; exit(EXIT_SUCCESS); } catch (const std::exception& e) { std::cout << "Abnormal termination - exception:" << e.what() << std::endl; exit(EXIT_FAILURE); } cpp-netlib-0.11.2-final/libs/network/example/http_client.cpp000066400000000000000000000051251256751517300240340ustar00rootroot00000000000000 // Copyright 2008, 2014 Dean Michael Berris // Copyright 2014 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //[ http_client_main /*` This application takes a URL as a command line argument and prints the resource to the console. */ #include #include #include #include #include namespace po = boost::program_options; int main(int argc, char* argv[]) { using namespace boost::network; po::options_description options("Allowed options"); std::string output_filename, source; bool show_headers; options.add_options()("help,h", "produce help message")( "headers,H", "print headers")("status,S", "print status and message")( "source,s", po::value(&source), "source URL"); po::positional_options_description positional_options; positional_options.add("source", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv) .options(options) .positional(positional_options) .run(), vm); po::notify(vm); } catch (std::exception& e) { std::cout << "Error: " << e.what() << std::endl; std::cout << options << std::endl; return EXIT_FAILURE; } if (vm.count("help")) { std::cout << options << std::endl; return EXIT_SUCCESS; } if (vm.count("source") < 1) { std::cout << "Error: Source URL required." << std::endl; std::cout << options << std::endl; return EXIT_FAILURE; } show_headers = vm.count("headers") ? true : false; bool show_status = vm.count("status") ? true : false; http::client::request request(source); http::client::string_type destination_ = host(request); request << ::boost::network::header("Connection", "close"); http::client::options client_options; client_options.follow_redirects(true); http::client client(client_options); http::client::response response = client.get(request); if (show_status) std::cout << status(response) << " " << status_message(response) << std::endl; if (show_headers) { headers_range::type headers_ = response.headers(); typedef std::pair header_type; BOOST_FOREACH(header_type const & header, headers_) { std::cout << header.first << ": " << header.second << std::endl; } std::cout << std::endl; } std::cout << body(response); return EXIT_SUCCESS; } //] cpp-netlib-0.11.2-final/libs/network/example/http_client1.cpp000066400000000000000000000012551256751517300241150ustar00rootroot00000000000000// Copyright Dean Michael Berris 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include int main(int argc, char* argv[]) { using namespace boost::network; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; return 0; } cpp-netlib-0.11.2-final/libs/network/example/rapidxml/000077500000000000000000000000001256751517300226305ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/rapidxml/license.txt000066400000000000000000000053001256751517300250110ustar00rootroot00000000000000Use of this software is granted under one of the following two licenses, to be chosen freely by the user. 1. Boost Software License - Version 1.0 - August 17th, 2003 =============================================================================== Copyright (c) 2006, 2007 Marcin Kalicinski Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2. The MIT License =============================================================================== Copyright (c) 2006, 2007 Marcin Kalicinski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cpp-netlib-0.11.2-final/libs/network/example/rapidxml/manual.html000066400000000000000000003347131256751517300250060ustar00rootroot00000000000000

RAPIDXML Manual

Version 1.13

Copyright (C) 2006, 2009 Marcin Kalicinski
See accompanying file
license.txt for license information.

Table of Contents

1. What is RapidXml?
1.1 Dependencies And Compatibility
1.2 Character Types And Encodings
1.3 Error Handling
1.4 Memory Allocation
1.5 W3C Compliance
1.6 API Design
1.7 Reliability
1.8 Acknowledgements
2. Two Minute Tutorial
2.1 Parsing
2.2 Accessing The DOM Tree
2.3 Modifying The DOM Tree
2.4 Printing XML
3. Differences From Regular XML Parsers
3.1 Lifetime Of Source Text
3.2 Ownership Of Strings
3.3 Destructive Vs Non-Destructive Mode
4. Performance
4.1 Comparison With Other Parsers
5. Reference

1. What is RapidXml?

RapidXml is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of strlen() function executed on the same data.

Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy rapidxml.hpp file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header rapidxml_print.hpp.

1.1 Dependencies And Compatibility

RapidXml has no dependencies other than a very small subset of standard C++ library (<cassert>, <cstdlib>, <new> and <exception>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.

1.2 Character Types And Encodings

RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse wchar_t strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag).

Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: &apos; &amp; &quot; &lt; &gt; &#...; Other character references are not expanded.

1.3 Error Handling

By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See parse_error class and parse_error_handler() function for more information.

1.4 Memory Allocation

RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using new operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of memory_pool::set_allocator() function. See class memory_pool for more information.

1.5 W3C Compliance

RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.

1.6 API Design

RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: rapidxml_utils.hpp and rapidxml_print.hpp. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).

1.7 Reliability

RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely.

Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents.

Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.

1.8 Acknowledgements

I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

2. Two Minute Tutorial

2.1 Parsing

The following code causes RapidXml to parse a zero-terminated string named text:
using namespace rapidxml;
xml_document<> doc;    // character type defaults to char
doc.parse<0>(text);    // 0 means default parse flags
doc object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace rapidxml, users must either bring contents of this namespace into scope, or fully qualify all the names. Class xml_document represents a root of the DOM hierarchy. By means of public inheritance, it is also an xml_node and a memory_pool. Template parameter of xml_document::parse() function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.

2.2 Accessing The DOM Tree

To access the DOM tree, use methods of xml_node and xml_attribute classes:
cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
xml_node<> *node = doc.first_node("foobar");
cout << "Node foobar has value " << node->value() << "\n";
for (xml_attribute<> *attr = node->first_attribute();
     attr; attr = attr->next_attribute())
{
    cout << "Node foobar has attribute " << attr->name() << " ";
    cout << "with value " << attr->value() << "\n";
}

2.3 Modifying The DOM Tree

DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website:
xml_document<> doc;
xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
doc.append_node(node);
xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
node->append_attribute(attr);
One quirk is that nodes and attributes do not own the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the xml_document memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses memory_pool::allocate_string() function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node:
xml_document<> doc;
char *node_name = doc.allocate_string(name);        // Allocate string and copy name into it
xml_node<> *node = doc.allocate_node(node_element, node_name);  // Set node name to node_name
Check Reference section for description of the entire interface.

2.4 Printing XML

You can print xml_document and xml_node objects into an XML string. Use print() function or operator <<, which are defined in rapidxml_print.hpp header.
using namespace rapidxml;
xml_document<> doc;    // character type defaults to char
// ... some code to fill the document

// Print to stream using operator <<
std::cout << doc;   

// Print to stream using print function, specifying printing flags
print(std::cout, doc, 0);   // 0 means default printing flags

// Print to string using output iterator
std::string s;
print(std::back_inserter(s), doc, 0);

// Print to memory buffer using output iterator
char buffer[4096];                      // You are responsible for making the buffer large enough!
char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
*end = 0;                               // Add string terminator after XML

3. Differences From Regular XML Parsers

RapidXml is an in-situ parser, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the source text in the DOM hierarchy.

3.1 Lifetime Of Source Text

In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml.

In many cases however, these are not serious issues.

3.2 Ownership Of Strings

Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using xml_base::name(const Ch *) or xml_base::value(const Ch *) functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from memory_pool owned by the document. Use memory_pool::allocate_string() function for this purpose.

3.3 Destructive Vs Non-Destructive Mode

By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.

In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:

4. Performance

RapidXml achieves its speed through use of several techniques:
  • In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.
  • Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.
  • Extensive use of lookup tables for parsing.
  • Hand-tuned C++ with profiling done on several most popular CPUs.
This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.

4.1 Comparison With Other Parsers

The table below compares speed of RapidXml to some other parsers, and to strlen() function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.
  • The test file is a real-world, 50kB large, moderately dense XML file.
  • All timing is done by using RDTSC instruction present in Pentium-compatible CPUs.
  • No profile-guided optimizations are used.
  • All parsers are running in their fastest modes.
  • The results are given in CPU cycles per character, so frequency of CPUs is irrelevant.
  • The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc.
  • A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results.
Platform
Compiler
strlen() RapidXml pugixml 0.3 pugxml TinyXml
Pentium 4
MSVC 8.0
2.5
5.4
7.0
61.7
298.8
Pentium 4
gcc 4.1.1
0.8
6.1
9.5
67.0
413.2
Core 2
MSVC 8.0
1.0
4.5
5.0
24.6
154.8
Core 2
gcc 4.1.1
0.6
4.6
5.4
28.3
229.3
Athlon XP
MSVC 8.0
3.1
7.7
8.0
25.5
182.6
Athlon XP
gcc 4.1.1
0.9
8.2
9.2
33.7
265.2
Pentium 3
MSVC 8.0
2.0
6.3
7.0
30.9
211.9
Pentium 3
gcc 4.1.1
1.0
6.7
8.9
35.3
316.0
(*) All results are in CPU cycles per character of source text

5. Reference

This section lists all classes, functions, constants etc. and describes them in detail.
class template rapidxml::memory_pool
constructor memory_pool()
destructor ~memory_pool()
function allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_string(const Ch *source=0, std::size_t size=0)
function clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)
function clear()
function set_allocator(alloc_func *af, free_func *ff)

class rapidxml::parse_error
constructor parse_error(const char *what, void *where)
function what() const
function where() const

class template rapidxml::xml_attribute
constructor xml_attribute()
function document() const
function previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const

class template rapidxml::xml_base
constructor xml_base()
function name() const
function name_size() const
function value() const
function value_size() const
function name(const Ch *name, std::size_t size)
function name(const Ch *name)
function value(const Ch *value, std::size_t size)
function value(const Ch *value)
function parent() const

class template rapidxml::xml_document
constructor xml_document()
function parse(Ch *text)
function clear()

class template rapidxml::xml_node
constructor xml_node(node_type type)
function type() const
function document() const
function first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function type(node_type type)
function prepend_node(xml_node< Ch > *child)
function append_node(xml_node< Ch > *child)
function insert_node(xml_node< Ch > *where, xml_node< Ch > *child)
function remove_first_node()
function remove_last_node()
function remove_node(xml_node< Ch > *where)
function remove_all_nodes()
function prepend_attribute(xml_attribute< Ch > *attribute)
function append_attribute(xml_attribute< Ch > *attribute)
function insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)
function remove_first_attribute()
function remove_last_attribute()
function remove_attribute(xml_attribute< Ch > *where)
function remove_all_attributes()

namespace rapidxml
enum node_type
function parse_error_handler(const char *what, void *where)
function print(OutIt out, const xml_node< Ch > &node, int flags=0)
function print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0)
function operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
constant parse_no_data_nodes
constant parse_no_element_values
constant parse_no_string_terminators
constant parse_no_entity_translation
constant parse_no_utf8
constant parse_declaration_node
constant parse_comment_nodes
constant parse_doctype_node
constant parse_pi_nodes
constant parse_validate_closing_tags
constant parse_trim_whitespace
constant parse_normalize_whitespace
constant parse_default
constant parse_non_destructive
constant parse_fastest
constant parse_full
constant print_no_indenting


class template rapidxml::memory_pool

Defined in rapidxml.hpp
Base class for xml_document

Description

This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use memory_pool of relevant xml_document to allocate the memory. Not only is this faster than allocating them by using new operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management.

Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. You can also call allocate_string() function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no free() function -- all allocations are freed at once when clear() function is called, or when the pool is destroyed.

It is also possible to create a standalone memory_pool, and use it to allocate nodes, whose lifetime will not be tied to any document.

Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, by using global new[] and delete[] operators. This behaviour can be changed by setting custom allocation routines. Use set_allocator() function to set them.

Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. This value defaults to the size of pointer on target architecture.

To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT to obtain best wasted memory to performance compromise. To do it, define their values before rapidxml.hpp file is included.

Parameters

Ch
Character type of created nodes.

constructor memory_pool::memory_pool

Synopsis

memory_pool();

Description

Constructs empty pool with default allocator functions.

destructor memory_pool::~memory_pool

Synopsis

~memory_pool();

Description

Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid.

function memory_pool::allocate_node

Synopsis

xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);

Description

Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

type
Type of node to create.
name
Name to assign to the node, or 0 to assign no name.
value
Value to assign to the node, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated node. This pointer will never be NULL.

function memory_pool::allocate_attribute

Synopsis

xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);

Description

Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

name
Name to assign to the attribute, or 0 to assign no name.
value
Value to assign to the attribute, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated attribute. This pointer will never be NULL.

function memory_pool::allocate_string

Synopsis

Ch* allocate_string(const Ch *source=0, std::size_t size=0);

Description

Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

source
String to initialize the allocated memory with, or 0 to not initialize it.
size
Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.

Returns

Pointer to allocated char array. This pointer will never be NULL.

function memory_pool::clone_node

Synopsis

xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0);

Description

Clones an xml_node and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document.

Parameters

source
Node to clone.
result
Node to put results in, or 0 to automatically allocate result node

Returns

Pointer to cloned node. This pointer will never be NULL.

function memory_pool::clear

Synopsis

void clear();

Description

Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid.

function memory_pool::set_allocator

Synopsis

void set_allocator(alloc_func *af, free_func *ff);

Description

Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use longjmp() function to pass control to other place of program. If it returns invalid pointer, results are undefined.

User defined allocation functions must have the following forms:

void *allocate(std::size_t size);
void free(void *pointer);

Parameters

af
Allocation function, or 0 to restore default function
ff
Free function, or 0 to restore default function

class rapidxml::parse_error

Defined in rapidxml.hpp

Description

Parse error exception. This exception is thrown by the parser when an error occurs. Use what() function to get human-readable error message. Use where() function to get a pointer to position within source text where error was detected.

If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. This function must be defined by the user.

This class derives from std::exception class.

constructor parse_error::parse_error

Synopsis

parse_error(const char *what, void *where);

Description

Constructs parse error.

function parse_error::what

Synopsis

virtual const char* what() const;

Description

Gets human readable description of error.

Returns

Pointer to null terminated description of the error.

function parse_error::where

Synopsis

Ch* where() const;

Description

Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.

Returns

Pointer to location within the parsed string where error occured.

class template rapidxml::xml_attribute

Defined in rapidxml.hpp
Inherits from xml_base

Description

Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.

Parameters

Ch
Character type to use.

constructor xml_attribute::xml_attribute

Synopsis

xml_attribute();

Description

Constructs an empty attribute with the specified type. Consider using memory_pool of appropriate xml_document if allocating attributes manually.

function xml_attribute::document

Synopsis

xml_document<Ch>* document() const;

Description

Gets document of which attribute is a child.

Returns

Pointer to document that contains this attribute, or 0 if there is no parent document.

function xml_attribute::previous_attribute

Synopsis

xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets previous attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_attribute::next_attribute

Synopsis

xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets next attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

class template rapidxml::xml_base

Defined in rapidxml.hpp
Base class for xml_attribute xml_node

Description

Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().

Parameters

Ch
Character type to use

constructor xml_base::xml_base

Synopsis

xml_base();

function xml_base::name

Synopsis

Ch* name() const;

Description

Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

Use name_size() function to determine length of the name.

Returns

Name of node, or empty string if node has no name.

function xml_base::name_size

Synopsis

std::size_t name_size() const;

Description

Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated.

Returns

Size of node name, in characters.

function xml_base::value

Synopsis

Ch* value() const;

Description

Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

Use value_size() function to determine length of the value.

Returns

Value of node, or empty string if node has no value.

function xml_base::value_size

Synopsis

std::size_t value_size() const;

Description

Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated.

Returns

Size of node value, in characters.

function xml_base::name

Synopsis

void name(const Ch *name, std::size_t size);

Description

Sets name of node to a non zero-terminated string. See Ownership Of Strings .

Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

Size of name must be specified separately, because name does not have to be zero terminated. Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

Parameters

name
Name of node to set. Does not have to be zero terminated.
size
Size of name, in characters. This does not include zero terminator, if one is present.

function xml_base::name

Synopsis

void name(const Ch *name);

Description

Sets name of node to a zero-terminated string. See also Ownership Of Strings and xml_node::name(const Ch *, std::size_t).

Parameters

name
Name of node to set. Must be zero terminated.

function xml_base::value

Synopsis

void value(const Ch *value, std::size_t size);

Description

Sets value of node to a non zero-terminated string. See Ownership Of Strings .

Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

Size of value must be specified separately, because it does not have to be zero terminated. Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.

Parameters

value
value of node to set. Does not have to be zero terminated.
size
Size of value, in characters. This does not include zero terminator, if one is present.

function xml_base::value

Synopsis

void value(const Ch *value);

Description

Sets value of node to a zero-terminated string. See also Ownership Of Strings and xml_node::value(const Ch *, std::size_t).

Parameters

value
Vame of node to set. Must be zero terminated.

function xml_base::parent

Synopsis

xml_node<Ch>* parent() const;

Description

Gets node parent.

Returns

Pointer to parent node, or 0 if there is no parent.

class template rapidxml::xml_document

Defined in rapidxml.hpp
Inherits from xml_node memory_pool

Description

This class represents root of the DOM hierarchy. It is also an xml_node and a memory_pool through public inheritance. Use parse() function to build a DOM tree from a zero-terminated XML text string. parse() function allocates memory for nodes and attributes by using functions of xml_document, which are inherited from memory_pool. To access root node of the document, use the document itself, as if it was an xml_node.

Parameters

Ch
Character type to use.

constructor xml_document::xml_document

Synopsis

xml_document();

Description

Constructs empty XML document.

function xml_document::parse

Synopsis

void parse(Ch *text);

Description

Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. The string must persist for the lifetime of the document. In case of error, rapidxml::parse_error exception will be thrown.

If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated.

Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

Parameters

text
XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

function xml_document::clear

Synopsis

void clear();

Description

Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed.

class template rapidxml::xml_node

Defined in rapidxml.hpp
Inherits from xml_base
Base class for xml_document

Description

Class representing a node of XML document. Each node may have associated name and value strings, which are available through name() and value() functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using type() function.

Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node.

Parameters

Ch
Character type to use.

constructor xml_node::xml_node

Synopsis

xml_node(node_type type);

Description

Constructs an empty node with the specified type. Consider using memory_pool of appropriate document to allocate nodes manually.

Parameters

type
Type of node to construct.

function xml_node::type

Synopsis

node_type type() const;

Description

Gets type of node.

Returns

Type of node.

function xml_node::document

Synopsis

xml_document<Ch>* document() const;

Description

Gets document of which node is a child.

Returns

Pointer to document that contains this node, or 0 if there is no parent document.

function xml_node::first_node

Synopsis

xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets first child node, optionally matching node name.

Parameters

name
Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::last_node

Synopsis

xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use first_node() to test if node has children.

Parameters

name
Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::previous_sibling

Synopsis

xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::next_sibling

Synopsis

xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::first_attribute

Synopsis

xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets first attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::last_attribute

Synopsis

xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;

Description

Gets last attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::type

Synopsis

void type(node_type type);

Description

Sets type of node.

Parameters

type
Type of node to set.

function xml_node::prepend_node

Synopsis

void prepend_node(xml_node< Ch > *child);

Description

Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back.

Parameters

child
Node to prepend.

function xml_node::append_node

Synopsis

void append_node(xml_node< Ch > *child);

Description

Appends a new child node. The appended child becomes the last child.

Parameters

child
Node to append.

function xml_node::insert_node

Synopsis

void insert_node(xml_node< Ch > *where, xml_node< Ch > *child);

Description

Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back.

Parameters

where
Place where to insert the child, or 0 to insert at the back.
child
Node to insert.

function xml_node::remove_first_node

Synopsis

void remove_first_node();

Description

Removes first child node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_last_node

Synopsis

void remove_last_node();

Description

Removes last child of the node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_node

Synopsis

void remove_node(xml_node< Ch > *where);

Description

Removes specified child from the node.

function xml_node::remove_all_nodes

Synopsis

void remove_all_nodes();

Description

Removes all child nodes (but not attributes).

function xml_node::prepend_attribute

Synopsis

void prepend_attribute(xml_attribute< Ch > *attribute);

Description

Prepends a new attribute to the node.

Parameters

attribute
Attribute to prepend.

function xml_node::append_attribute

Synopsis

void append_attribute(xml_attribute< Ch > *attribute);

Description

Appends a new attribute to the node.

Parameters

attribute
Attribute to append.

function xml_node::insert_attribute

Synopsis

void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute);

Description

Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.

Parameters

where
Place where to insert the attribute, or 0 to insert at the back.
attribute
Attribute to insert.

function xml_node::remove_first_attribute

Synopsis

void remove_first_attribute();

Description

Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_last_attribute

Synopsis

void remove_last_attribute();

Description

Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_attribute

Synopsis

void remove_attribute(xml_attribute< Ch > *where);

Description

Removes specified attribute from node.

Parameters

where
Pointer to attribute to be removed.

function xml_node::remove_all_attributes

Synopsis

void remove_all_attributes();

Description

Removes all attributes of node.

enum node_type

Description

Enumeration listing all node types produced by the parser. Use xml_node::type() function to query node type.

Values

node_document
A document node. Name and value are empty.
node_element
An element node. Name contains element name. Value contains text of first data node.
node_data
A data node. Name is empty. Value contains data text.
node_cdata
A CDATA node. Name is empty. Value contains data text.
node_comment
A comment node. Name is empty. Value contains comment text.
node_declaration
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
node_doctype
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
node_pi
A PI node. Name contains target. Value contains instructions.

function parse_error_handler

Synopsis

void rapidxml::parse_error_handler(const char *what, void *where);

Description

When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user.

This function cannot return. If it does, the results are undefined.

A very simple definition might look like that: void rapidxml::parse_error_handler(const char *what, void *where) { std::cout << "Parse error: " << what << "\n"; std::abort(); }

Parameters

what
Human readable description of the error.
where
Pointer to character data where error was detected.

function print

Synopsis

OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0);

Description

Prints XML to given output iterator.

Parameters

out
Output iterator to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output iterator pointing to position immediately after last character of printed text.

function print

Synopsis

std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0);

Description

Prints XML to given output stream.

Parameters

out
Output stream to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output stream.

function operator<<

Synopsis

std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node);

Description

Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.

Parameters

out
Output stream to print to.
node
Node to be printed.

Returns

Output stream.

constant parse_no_data_nodes

Synopsis

const int parse_no_data_nodes = 0x1;

Description

Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_no_element_values

Synopsis

const int parse_no_element_values = 0x2;

Description

Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes and a value, the value will be ignored. Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

See xml_document::parse() function.

constant parse_no_string_terminators

Synopsis

const int parse_no_string_terminators = 0x4;

Description

Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_no_entity_translation

Synopsis

const int parse_no_entity_translation = 0x8;

Description

Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_no_utf8

Synopsis

const int parse_no_utf8 = 0x10;

Description

Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_declaration_node

Synopsis

const int parse_declaration_node = 0x20;

Description

Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_comment_nodes

Synopsis

const int parse_comment_nodes = 0x40;

Description

Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_doctype_node

Synopsis

const int parse_doctype_node = 0x80;

Description

Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_pi_nodes

Synopsis

const int parse_pi_nodes = 0x100;

Description

Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_validate_closing_tags

Synopsis

const int parse_validate_closing_tags = 0x200;

Description

Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_trim_whitespace

Synopsis

const int parse_trim_whitespace = 0x400;

Description

Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_normalize_whitespace

Synopsis

const int parse_normalize_whitespace = 0x800;

Description

Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator.

See xml_document::parse() function.

constant parse_default

Synopsis

const int parse_default = 0;

Description

Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a negation of the default setting. For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, and using the flag will disable it.

See xml_document::parse() function.

constant parse_non_destructive

Synopsis

const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;

Description

A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur:
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • entities will not be translated
  • whitespace will not be normalized
See xml_document::parse() function.

constant parse_fastest

Synopsis

const int parse_fastest = parse_non_destructive | parse_no_data_nodes;

Description

A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

See xml_document::parse() function.

constant parse_full

Synopsis

const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;

Description

A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing.

See xml_document::parse() function.

constant print_no_indenting

Synopsis

const int print_no_indenting = 0x1;

Description

Printer flag instructing the printer to suppress indenting of XML. See print() function.

cpp-netlib-0.11.2-final/libs/network/example/rapidxml/rapidxml.hpp000066400000000000000000003053361256751517300251730ustar00rootroot00000000000000#ifndef RAPIDXML_HPP_INCLUDED #define RAPIDXML_HPP_INCLUDED // Copyright (C) 2006, 2009 Marcin Kalicinski // Version 1.13 // Revision $DateTime: 2009/05/13 01:46:17 $ //! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation // If standard library is disabled, user must provide implementations of // required functions and typedefs #if !defined(RAPIDXML_NO_STDLIB) #include // For std::size_t #include // For assert #include // For placement new #endif // On MSVC, disable "conditional expression is constant" warning (level 4). // This warning is almost impossible to avoid with certain types of templated // code #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4127) // Conditional expression is constant #endif /////////////////////////////////////////////////////////////////////////// // RAPIDXML_PARSE_ERROR #if defined(RAPIDXML_NO_EXCEPTIONS) #define RAPIDXML_PARSE_ERROR(what, where) \ { \ parse_error_handler(what, where); \ assert(0); \ } namespace rapidxml { //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, //! this function is called to notify user about the error. //! It must be defined by the user. //!

//! This function cannot return. If it does, the results are undefined. //!

//! A very simple definition might look like that: //!

//! void %rapidxml::%parse_error_handler(const char *what, void *where)
//! {
//!     std::cout << "Parse error: " << what << "\n";
//!     std::abort();
//! }
//! 
//! \param what Human readable description of the error. //! \param where Pointer to character data where error was detected. void parse_error_handler(const char *what, void *where); } #else #include // For std::exception #define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) namespace rapidxml { //! Parse error exception. //! This exception is thrown by the parser when an error occurs. //! Use what() function to get human-readable error message. //! Use where() function to get a pointer to position within source text where // error was detected. //!

//! If throwing exceptions by the parser is undesirable, //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before // rapidxml.hpp is included. //! This will cause the parser to call rapidxml::parse_error_handler() // function instead of throwing an exception. //! This function must be defined by the user. //!

//! This class derives from std::exception class. class parse_error : public std::exception { public: //! Constructs parse error parse_error(const char *what, void *where) : m_what(what), m_where(where) {} //! Gets human readable description of error. //! \return Pointer to null terminated description of the error. virtual const char *what() const throw() { return m_what; } //! Gets pointer to character data where error happened. //! Ch should be the same as char type of xml_document that produced the // error. //! \return Pointer to location within the parsed string where error // occured. template Ch *where() const { return reinterpret_cast(m_where); } private: const char *m_what; void *m_where; }; } #endif /////////////////////////////////////////////////////////////////////////// // Pool sizes #ifndef RAPIDXML_STATIC_POOL_SIZE // Size of static memory block of memory_pool. // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to // override the default value. // No dynamic memory allocations are performed by memory_pool until static // memory is exhausted. #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) #endif #ifndef RAPIDXML_DYNAMIC_POOL_SIZE // Size of dynamic memory block of memory_pool. // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want // to override the default value. // After the static block is exhausted, dynamic blocks with approximately this // size are allocated by memory_pool. #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) #endif #ifndef RAPIDXML_ALIGNMENT // Memory allocation alignment. // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to // override the default value, which is the size of pointer. // All memory allocations for nodes, attributes and strings will be aligned to // this value. // This must be a power of 2 and at least 1, otherwise memory_pool will not // work. #define RAPIDXML_ALIGNMENT sizeof(void *) #endif namespace rapidxml { // Forward declarations template class xml_node; template class xml_attribute; template class xml_document; //! Enumeration listing all node types produced by the parser. //! Use xml_node::type() function to query node type. enum node_type { node_document, //!< A document node. Name and value are empty. node_element, //!< An element node. Name contains element name. Value // contains text of first data node. node_data, //!< A data node. Name is empty. Value contains data text. node_cdata, //!< A CDATA node. Name is empty. Value contains data text. node_comment, //!< A comment node. Name is empty. Value contains comment // text. node_declaration, //!< A declaration node. Name and value are empty. // Declaration parameters (version, encoding and // standalone) are in node attributes. node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE // text. node_pi //!< A PI node. Name contains target. Value contains instructions. }; /////////////////////////////////////////////////////////////////////// // Parsing flags //! Parse flag instructing the parser to not create data nodes. //! Text of first data node will still be placed in value of parent element, // unless rapidxml::parse_no_element_values flag is also specified. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_no_data_nodes = 0x1; //! Parse flag instructing the parser to not use text of first data node as a // value of parent element. //! Can be combined with other flags by use of | operator. //! Note that child data nodes of element node take precendence over its value // when printing. //! That is, if element has one or more child data nodes and a value, // the value will be ignored. //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes // if you want to manipulate data using values of elements. //!

//! See xml_document::parse() function. const int parse_no_element_values = 0x2; //! Parse flag instructing the parser to not place zero terminators after // strings in the source text. //! By default zero terminators are placed, modifying source text. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_no_string_terminators = 0x4; //! Parse flag instructing the parser to not translate entities in the source // text. //! By default entities are translated, modifying source text. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_no_entity_translation = 0x8; //! Parse flag instructing the parser to disable UTF-8 handling and assume // plain 8 bit characters. //! By default, UTF-8 handling is enabled. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_no_utf8 = 0x10; //! Parse flag instructing the parser to create XML declaration node. //! By default, declaration node is not created. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_declaration_node = 0x20; //! Parse flag instructing the parser to create comments nodes. //! By default, comment nodes are not created. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_comment_nodes = 0x40; //! Parse flag instructing the parser to create DOCTYPE node. //! By default, doctype node is not created. //! Although W3C specification allows at most one DOCTYPE node, RapidXml will // silently accept documents with more than one. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_doctype_node = 0x80; //! Parse flag instructing the parser to create PI nodes. //! By default, PI nodes are not created. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_pi_nodes = 0x100; //! Parse flag instructing the parser to validate closing tag names. //! If not set, name inside closing tag is irrelevant to the parser. //! By default, closing tags are not validated. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_validate_closing_tags = 0x200; //! Parse flag instructing the parser to trim all leading and trailing // whitespace of data nodes. //! By default, whitespace is not trimmed. //! This flag does not cause the parser to modify source text. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_trim_whitespace = 0x400; //! Parse flag instructing the parser to condense all whitespace runs of data // nodes to a single space character. //! Trimming of leading and trailing whitespace of data is controlled by // rapidxml::parse_trim_whitespace flag. //! By default, whitespace is not normalized. //! If this flag is specified, source text will be modified. //! Can be combined with other flags by use of | operator. //!

//! See xml_document::parse() function. const int parse_normalize_whitespace = 0x800; // Compound flags //! Parse flags which represent default behaviour of the parser. //! This is always equal to 0, so that all other flags can be simply ored // together. //! Normally there is no need to inconveniently disable flags by anding with // their negated (~) values. //! This also means that meaning of each flag is a negation of the // default setting. //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 // is enabled by default, //! and using the flag will disable it. //!

//! See xml_document::parse() function. const int parse_default = 0; //! A combination of parse flags that forbids any modifications of the source // text. //! This also results in faster parsing. However, note that the following will // occur: //!
    //!
  • names and values of nodes will not be zero terminated, you have to use // xml_base::name_size() and xml_base::value_size() functions to determine // where name and value ends
  • //!
  • entities will not be translated
  • //!
  • whitespace will not be normalized
  • //!
//! See xml_document::parse() function. const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; //! A combination of parse flags resulting in fastest possible parsing, // without sacrificing important data. //!

//! See xml_document::parse() function. const int parse_fastest = parse_non_destructive | parse_no_data_nodes; //! A combination of parse flags resulting in largest amount of data being // extracted. //! This usually results in slowest parsing. //!

//! See xml_document::parse() function. const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; /////////////////////////////////////////////////////////////////////// // Internals //! \cond internal namespace internal { // Struct that contains lookup tables for the parser // It must be a template to allow correct linking (because it has static // data members, which are defined in a header file). template struct lookup_tables { static const unsigned char lookup_whitespace[256]; // Whitespace table static const unsigned char lookup_node_name[256]; // Node name table static const unsigned char lookup_text[256]; // Text table static const unsigned char lookup_text_pure_no_ws[256]; // Text table static const unsigned char lookup_text_pure_with_ws[256]; // Text table static const unsigned char lookup_attribute_name[256]; // Attribute name // table static const unsigned char lookup_attribute_data_1[256]; // Attribute // data table // with single // quote static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute // data table // with single // quote static const unsigned char lookup_attribute_data_2[256]; // Attribute // data table // with double // quotes static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute // data table // with double // quotes static const unsigned char lookup_digits[256]; // Digits static const unsigned char lookup_upcase[256]; // To uppercase conversion // table for ASCII // characters }; // Find length of the string template inline std::size_t measure(const Ch *p) { const Ch *tmp = p; while (*tmp) ++tmp; return tmp - p; } // Compare strings for equality template inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) { if (size1 != size2) return false; if (case_sensitive) { for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) if (*p1 != *p2) return false; } else { for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) return false; } return true; } } //! \endcond /////////////////////////////////////////////////////////////////////// // Memory pool //! This class is used by the parser to create new nodes and attributes, // without overheads of dynamic memory allocation. //! In most cases, you will not need to use this class directly. //! However, if you need to create nodes manually or modify names/values of // nodes, //! you are encouraged to use memory_pool of relevant xml_document to allocate // the memory. //! Not only is this faster than allocating them by using new // operator, //! but also their lifetime will be tied to the lifetime of document, //! possibly simplyfing memory management. //!

//! Call allocate_node() or allocate_attribute() functions to obtain new nodes // or attributes from the pool. //! You can also call allocate_string() function to allocate strings. //! Such strings can then be used as names or values of nodes without worrying // about their lifetime. //! Note that there is no free() function -- all allocations are // freed at once when clear() function is called, //! or when the pool is destroyed. //!

//! It is also possible to create a standalone memory_pool, and use it //! to allocate nodes, whose lifetime will not be tied to any document. //!

//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically // allocated memory. //! Until static memory is exhausted, no dynamic memory allocations are done. //! When static memory is exhausted, pool allocates additional blocks of // memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, //! by using global new[] and delete[] operators. //! This behaviour can be changed by setting custom allocation routines. //! Use set_allocator() function to set them. //!

//! Allocations for nodes, attributes and strings are aligned at //RAPIDXML_ALIGNMENT bytes. //! This value defaults to the size of pointer on target architecture. //!

//! To obtain absolutely top performance from the parser, //! it is important that all nodes are allocated from a single, contiguous // block of memory. //! Otherwise, cache misses when jumping between two (or more) disjoint blocks // of memory can slow down parsing quite considerably. //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, //RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT //! to obtain best wasted memory to performance compromise. //! To do it, define their values before rapidxml.hpp file is included. //! \param Ch Character type of created nodes. template class memory_pool { public: //! \cond internal typedef void *(alloc_func)(std::size_t); // Type of user-defined function // used to allocate memory typedef void(free_func)(void *); // Type of user-defined function used to // free memory //! \endcond //! Constructs empty pool with default allocator functions. memory_pool() : m_alloc_func(0), m_free_func(0) { init(); } //! Destroys pool and frees all the memory. //! This causes memory occupied by nodes allocated by the pool to be freed. //! Nodes allocated from the pool are no longer valid. ~memory_pool() { clear(); } //! Allocates a new node from the pool, and optionally assigns name and // value to it. //! If the allocation request cannot be accomodated, this function will // throw std::bad_alloc. //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this // function //! will call rapidxml::parse_error_handler() function. //! \param type Type of node to create. //! \param name Name to assign to the node, or 0 to assign no name. //! \param value Value to assign to the node, or 0 to assign no value. //! \param name_size Size of name to assign, or 0 to automatically calculate // size from name string. //! \param value_size Size of value to assign, or 0 to automatically // calculate size from value string. //! \return Pointer to allocated node. This pointer will never be NULL. xml_node *allocate_node(node_type type, const Ch *name = 0, const Ch *value = 0, std::size_t name_size = 0, std::size_t value_size = 0) { void *memory = allocate_aligned(sizeof(xml_node)); xml_node *node = new (memory) xml_node(type); if (name) { if (name_size > 0) node->name(name, name_size); else node->name(name); } if (value) { if (value_size > 0) node->value(value, value_size); else node->value(value); } return node; } //! Allocates a new attribute from the pool, and optionally assigns name and // value to it. //! If the allocation request cannot be accomodated, this function will // throw std::bad_alloc. //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this // function //! will call rapidxml::parse_error_handler() function. //! \param name Name to assign to the attribute, or 0 to assign no name. //! \param value Value to assign to the attribute, or 0 to assign no value. //! \param name_size Size of name to assign, or 0 to automatically calculate // size from name string. //! \param value_size Size of value to assign, or 0 to automatically // calculate size from value string. //! \return Pointer to allocated attribute. This pointer will never be NULL. xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, std::size_t name_size = 0, std::size_t value_size = 0) { void *memory = allocate_aligned(sizeof(xml_attribute)); xml_attribute *attribute = new (memory) xml_attribute; if (name) { if (name_size > 0) attribute->name(name, name_size); else attribute->name(name); } if (value) { if (value_size > 0) attribute->value(value, value_size); else attribute->value(value); } return attribute; } //! Allocates a char array of given size from the pool, and optionally // copies a given string to it. //! If the allocation request cannot be accomodated, this function will // throw std::bad_alloc. //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this // function //! will call rapidxml::parse_error_handler() function. //! \param source String to initialize the allocated memory with, or 0 to // not initialize it. //! \param size Number of characters to allocate, or zero to calculate it // automatically from source string length; if size is 0, source string must // be specified and null terminated. //! \return Pointer to allocated char array. This pointer will never be // NULL. Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { assert(source || size); // Either source or size (or both) must be specified if (size == 0) size = internal::measure(source) + 1; Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); if (source) for (std::size_t i = 0; i < size; ++i) result[i] = source[i]; return result; } //! Clones an xml_node and its hierarchy of child nodes and attributes. //! Nodes and attributes are allocated from this memory pool. //! Names and values are not cloned, they are shared between the clone and // the source. //! Result node can be optionally specified as a second parameter, //! in which case its contents will be replaced with cloned source node. //! This is useful when you want to clone entire document. //! \param source Node to clone. //! \param result Node to put results in, or 0 to automatically allocate // result node //! \return Pointer to cloned node. This pointer will never be NULL. xml_node *clone_node(const xml_node *source, xml_node *result = 0) { // Prepare result node if (result) { result->remove_all_attributes(); result->remove_all_nodes(); result->type(source->type()); } else result = allocate_node(source->type()); // Clone name and value result->name(source->name(), source->name_size()); result->value(source->value(), source->value_size()); // Clone child nodes and attributes for (xml_node *child = source->first_node(); child; child = child->next_sibling()) result->append_node(clone_node(child)); for (xml_attribute *attr = source->first_attribute(); attr; attr = attr->next_attribute()) result->append_attribute(allocate_attribute( attr->name(), attr->value(), attr->name_size(), attr->value_size())); return result; } //! Clears the pool. //! This causes memory occupied by nodes allocated by the pool to be freed. //! Any nodes or strings allocated from the pool will no longer be valid. void clear() { while (m_begin != m_static_memory) { char *previous_begin = reinterpret_cast
(align(m_begin))->previous_begin; if (m_free_func) m_free_func(m_begin); else delete[] m_begin; m_begin = previous_begin; } init(); } //! Sets or resets the user-defined memory allocation functions for the // pool. //! This can only be called when no memory is allocated from the pool yet, // otherwise results are undefined. //! Allocation function must not return invalid pointer on failure. It // should either throw, //! stop the program, or use longjmp() function to pass control // to other place of program. //! If it returns invalid pointer, results are undefined. //!

//! User defined allocation functions must have the following forms: //!
//!
void *allocate(std::size_t size); //!
void free(void *pointer); //!

//! \param af Allocation function, or 0 to restore default function //! \param ff Free function, or 0 to restore default function void set_allocator(alloc_func *af, free_func *ff) { assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet m_alloc_func = af; m_free_func = ff; } private: struct header { char *previous_begin; }; void init() { m_begin = m_static_memory; m_ptr = align(m_begin); m_end = m_static_memory + sizeof(m_static_memory); } char *align(char *ptr) { std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); return ptr + alignment; } char *allocate_raw(std::size_t size) { // Allocate void *memory; if (m_alloc_func) // Allocate memory using either user-specified // allocation function or global operator new[] { memory = m_alloc_func(size); assert(memory); // Allocator is not allowed to return 0, on failure it // must either throw, stop the program or use longjmp } else { memory = new char[size]; #ifdef RAPIDXML_NO_EXCEPTIONS if (!memory) // If exceptions are disabled, verify memory allocation, // because new will not be able to throw bad_alloc RAPIDXML_PARSE_ERROR("out of memory", 0); #endif } return static_cast(memory); } void *allocate_aligned(std::size_t size) { // Calculate aligned pointer char *result = align(m_ptr); // If not enough memory left in current pool, allocate a new pool if (result + size > m_end) { // Calculate required pool size (may be bigger than // RAPIDXML_DYNAMIC_POOL_SIZE) std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; if (pool_size < size) pool_size = size; // Allocate std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst // case: one for header, one for // actual allocation char *raw_memory = allocate_raw(alloc_size); // Setup new pool in allocated memory char *pool = align(raw_memory); header *new_header = reinterpret_cast
(pool); new_header->previous_begin = m_begin; m_begin = raw_memory; m_ptr = pool + sizeof(header); m_end = raw_memory + alloc_size; // Calculate aligned pointer again using new pool result = align(m_ptr); } // Update pool and return aligned pointer m_ptr = result + size; return result; } char *m_begin; // Start of raw memory making up current pool char *m_ptr; // First free byte in current pool char *m_end; // One past last available byte in current pool char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be // used free_func *m_free_func; // Free function, or 0 if default is to be used }; /////////////////////////////////////////////////////////////////////////// // XML base //! Base class for xml_node and xml_attribute implementing common functions: //! name(), name_size(), value(), value_size() and parent(). //! \param Ch Character type to use template class xml_base { public: /////////////////////////////////////////////////////////////////////////// // Construction & destruction // Construct a base with empty name, value and parent xml_base() : m_name(0), m_value(0), m_parent(0) {} /////////////////////////////////////////////////////////////////////////// // Node data access //! Gets name of the node. //! Interpretation of name depends on type of node. //! Note that name will not be zero-terminated if // rapidxml::parse_no_string_terminators option was selected during parse. //!

//! Use name_size() function to determine length of the name. //! \return Name of node, or empty string if node has no name. Ch *name() const { return m_name ? m_name : nullstr(); } //! Gets size of node name, not including terminator character. //! This function works correctly irrespective of whether name is or is not // zero terminated. //! \return Size of node name, in characters. std::size_t name_size() const { return m_name ? m_name_size : 0; } //! Gets value of node. //! Interpretation of value depends on type of node. //! Note that value will not be zero-terminated if // rapidxml::parse_no_string_terminators option was selected during parse. //!

//! Use value_size() function to determine length of the value. //! \return Value of node, or empty string if node has no value. Ch *value() const { return m_value ? m_value : nullstr(); } //! Gets size of node value, not including terminator character. //! This function works correctly irrespective of whether value is or is not // zero terminated. //! \return Size of node value, in characters. std::size_t value_size() const { return m_value ? m_value_size : 0; } /////////////////////////////////////////////////////////////////////////// // Node modification //! Sets name of node to a non zero-terminated string. //! See \ref ownership_of_strings. //!

//! Note that node does not own its name or value, it only stores a pointer // to it. //! It will not delete or otherwise free the pointer on destruction. //! It is reponsibility of the user to properly manage lifetime of the // string. //! The easiest way to achieve it is to use memory_pool of the document to // allocate the string - //! on destruction of the document the string will be automatically freed. //!

//! Size of name must be specified separately, because name does not have to // be zero terminated. //! Use name(const Ch *) function to have the length automatically // calculated (string must be zero terminated). //! \param name Name of node to set. Does not have to be zero terminated. //! \param size Size of name, in characters. This does not include zero // terminator, if one is present. void name(const Ch *name, std::size_t size) { m_name = const_cast(name); m_name_size = size; } //! Sets name of node to a zero-terminated string. //! See also \ref ownership_of_strings and xml_node::name(const Ch *, // std::size_t). //! \param name Name of node to set. Must be zero terminated. void name(const Ch *name) { this->name(name, internal::measure(name)); } //! Sets value of node to a non zero-terminated string. //! See \ref ownership_of_strings. //!

//! Note that node does not own its name or value, it only stores a pointer // to it. //! It will not delete or otherwise free the pointer on destruction. //! It is reponsibility of the user to properly manage lifetime of the // string. //! The easiest way to achieve it is to use memory_pool of the document to // allocate the string - //! on destruction of the document the string will be automatically freed. //!

//! Size of value must be specified separately, because it does not have to // be zero terminated. //! Use value(const Ch *) function to have the length automatically // calculated (string must be zero terminated). //!

//! If an element has a child node of type node_data, it will take // precedence over element value when printing. //! If you want to manipulate data of elements using values, use parser flag // rapidxml::parse_no_data_nodes to prevent creation of data nodes by the // parser. //! \param value value of node to set. Does not have to be zero terminated. //! \param size Size of value, in characters. This does not include zero // terminator, if one is present. void value(const Ch *value, std::size_t size) { m_value = const_cast(value); m_value_size = size; } //! Sets value of node to a zero-terminated string. //! See also \ref ownership_of_strings and xml_node::value(const Ch *, // std::size_t). //! \param value Vame of node to set. Must be zero terminated. void value(const Ch *value) { this->value(value, internal::measure(value)); } /////////////////////////////////////////////////////////////////////////// // Related nodes access //! Gets node parent. //! \return Pointer to parent node, or 0 if there is no parent. xml_node *parent() const { return m_parent; } protected: // Return empty string static Ch *nullstr() { static Ch zero = Ch('\0'); return &zero; } Ch *m_name; // Name of node, or 0 if no name Ch *m_value; // Value of node, or 0 if no value std::size_t m_name_size; // Length of node name, or undefined of no name std::size_t m_value_size; // Length of node value, or undefined if no value xml_node *m_parent; // Pointer to parent node, or 0 if none }; //! Class representing attribute node of XML document. //! Each attribute has name and value strings, which are available through // name() and value() functions (inherited from xml_base). //! Note that after parse, both name and value of attribute will point to // interior of source text used for parsing. //! Thus, this text must persist in memory for the lifetime of attribute. //! \param Ch Character type to use. template class xml_attribute : public xml_base { friend class xml_node; public: /////////////////////////////////////////////////////////////////////////// // Construction & destruction //! Constructs an empty attribute with the specified type. //! Consider using memory_pool of appropriate xml_document if allocating // attributes manually. xml_attribute() {} /////////////////////////////////////////////////////////////////////////// // Related nodes access //! Gets document of which attribute is a child. //! \return Pointer to document that contains this attribute, or 0 if there // is no parent document. xml_document *document() const { if (xml_node *node = this->parent()) { while (node->parent()) node = node->parent(); return node->type() == node_document ? static_cast *>(node) : 0; } else return 0; } //! Gets previous attribute, optionally matching attribute name. //! \param name Name of attribute to find, or 0 to return previous attribute // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) return attribute; return 0; } else return this->m_parent ? m_prev_attribute : 0; } //! Gets next attribute, optionally matching attribute name. //! \param name Name of attribute to find, or 0 to return next attribute // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) return attribute; return 0; } else return this->m_parent ? m_next_attribute : 0; } private: xml_attribute *m_prev_attribute; // Pointer to previous sibling of // attribute, or 0 if none; only valid // if parent is non-zero xml_attribute *m_next_attribute; // Pointer to next sibling of // attribute, or 0 if none; only valid // if parent is non-zero }; /////////////////////////////////////////////////////////////////////////// // XML node //! Class representing a node of XML document. //! Each node may have associated name and value strings, which are available // through name() and value() functions. //! Interpretation of name and value depends on type of the node. //! Type of node can be determined by using type() function. //!

//! Note that after parse, both name and value of node, if any, will point // interior of source text used for parsing. //! Thus, this text must persist in the memory for the lifetime of node. //! \param Ch Character type to use. template class xml_node : public xml_base { public: /////////////////////////////////////////////////////////////////////////// // Construction & destruction //! Constructs an empty node with the specified type. //! Consider using memory_pool of appropriate document to allocate nodes // manually. //! \param type Type of node to construct. xml_node(node_type type) : m_type(type), m_first_node(0), m_first_attribute(0) {} /////////////////////////////////////////////////////////////////////////// // Node data access //! Gets type of node. //! \return Type of node. node_type type() const { return m_type; } /////////////////////////////////////////////////////////////////////////// // Related nodes access //! Gets document of which node is a child. //! \return Pointer to document that contains this node, or 0 if there is no // parent document. xml_document *document() const { xml_node *node = const_cast *>(this); while (node->parent()) node = node->parent(); return node->type() == node_document ? static_cast *>(node) : 0; } //! Gets first child node, optionally matching node name. //! \param name Name of child to find, or 0 to return first child regardless // of its name; this string doesn't have to be zero-terminated if name_size // is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found child, or 0 if not found. xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_node *child = m_first_node; child; child = child->next_sibling()) if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) return child; return 0; } else return m_first_node; } //! Gets last child node, optionally matching node name. //! Behaviour is undefined if node has no children. //! Use first_node() to test if node has children. //! \param name Name of child to find, or 0 to return last child regardless // of its name; this string doesn't have to be zero-terminated if name_size // is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found child, or 0 if not found. xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { assert( m_first_node); // Cannot query for last child if node has no children if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_node *child = m_last_node; child; child = child->previous_sibling()) if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) return child; return 0; } else return m_last_node; } //! Gets previous sibling node, optionally matching node name. //! Behaviour is undefined if node has no parent. //! Use parent() to test if node has a parent. //! \param name Name of sibling to find, or 0 to return previous sibling // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found sibling, or 0 if not found. xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { assert(this->m_parent); // Cannot query for siblings if node has no parent if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) return sibling; return 0; } else return m_prev_sibling; } //! Gets next sibling node, optionally matching node name. //! Behaviour is undefined if node has no parent. //! Use parent() to test if node has a parent. //! \param name Name of sibling to find, or 0 to return next sibling // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found sibling, or 0 if not found. xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { assert(this->m_parent); // Cannot query for siblings if node has no parent if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) return sibling; return 0; } else return m_next_sibling; } //! Gets first attribute of node, optionally matching attribute name. //! \param name Name of attribute to find, or 0 to return first attribute // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) return attribute; return 0; } else return m_first_attribute; } //! Gets last attribute of node, optionally matching attribute name. //! \param name Name of attribute to find, or 0 to return last attribute // regardless of its name; this string doesn't have to be zero-terminated if // name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size // calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non // case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const { if (name) { if (name_size == 0) name_size = internal::measure(name); for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) return attribute; return 0; } else return m_first_attribute ? m_last_attribute : 0; } /////////////////////////////////////////////////////////////////////////// // Node modification //! Sets type of node. //! \param type Type of node to set. void type(node_type type) { m_type = type; } /////////////////////////////////////////////////////////////////////////// // Node manipulation //! Prepends a new child node. //! The prepended child becomes the first child, and all existing children // are moved one position back. //! \param child Node to prepend. void prepend_node(xml_node *child) { assert(child && !child->parent() && child->type() != node_document); if (first_node()) { child->m_next_sibling = m_first_node; m_first_node->m_prev_sibling = child; } else { child->m_next_sibling = 0; m_last_node = child; } m_first_node = child; child->m_parent = this; child->m_prev_sibling = 0; } //! Appends a new child node. //! The appended child becomes the last child. //! \param child Node to append. void append_node(xml_node *child) { assert(child && !child->parent() && child->type() != node_document); if (first_node()) { child->m_prev_sibling = m_last_node; m_last_node->m_next_sibling = child; } else { child->m_prev_sibling = 0; m_first_node = child; } m_last_node = child; child->m_parent = this; child->m_next_sibling = 0; } //! Inserts a new child node at specified place inside the node. //! All children after and including the specified node are moved one // position back. //! \param where Place where to insert the child, or 0 to insert at the // back. //! \param child Node to insert. void insert_node(xml_node *where, xml_node *child) { assert(!where || where->parent() == this); assert(child && !child->parent() && child->type() != node_document); if (where == m_first_node) prepend_node(child); else if (where == 0) append_node(child); else { child->m_prev_sibling = where->m_prev_sibling; child->m_next_sibling = where; where->m_prev_sibling->m_next_sibling = child; where->m_prev_sibling = child; child->m_parent = this; } } //! Removes first child node. //! If node has no children, behaviour is undefined. //! Use first_node() to test if node has children. void remove_first_node() { assert(first_node()); xml_node *child = m_first_node; m_first_node = child->m_next_sibling; if (child->m_next_sibling) child->m_next_sibling->m_prev_sibling = 0; else m_last_node = 0; child->m_parent = 0; } //! Removes last child of the node. //! If node has no children, behaviour is undefined. //! Use first_node() to test if node has children. void remove_last_node() { assert(first_node()); xml_node *child = m_last_node; if (child->m_prev_sibling) { m_last_node = child->m_prev_sibling; child->m_prev_sibling->m_next_sibling = 0; } else m_first_node = 0; child->m_parent = 0; } //! Removes specified child from the node // \param where Pointer to child to be removed. void remove_node(xml_node *where) { assert(where && where->parent() == this); assert(first_node()); if (where == m_first_node) remove_first_node(); else if (where == m_last_node) remove_last_node(); else { where->m_prev_sibling->m_next_sibling = where->m_next_sibling; where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; where->m_parent = 0; } } //! Removes all child nodes (but not attributes). void remove_all_nodes() { for (xml_node *node = first_node(); node; node = node->m_next_sibling) node->m_parent = 0; m_first_node = 0; } //! Prepends a new attribute to the node. //! \param attribute Attribute to prepend. void prepend_attribute(xml_attribute *attribute) { assert(attribute && !attribute->parent()); if (first_attribute()) { attribute->m_next_attribute = m_first_attribute; m_first_attribute->m_prev_attribute = attribute; } else { attribute->m_next_attribute = 0; m_last_attribute = attribute; } m_first_attribute = attribute; attribute->m_parent = this; attribute->m_prev_attribute = 0; } //! Appends a new attribute to the node. //! \param attribute Attribute to append. void append_attribute(xml_attribute *attribute) { assert(attribute && !attribute->parent()); if (first_attribute()) { attribute->m_prev_attribute = m_last_attribute; m_last_attribute->m_next_attribute = attribute; } else { attribute->m_prev_attribute = 0; m_first_attribute = attribute; } m_last_attribute = attribute; attribute->m_parent = this; attribute->m_next_attribute = 0; } //! Inserts a new attribute at specified place inside the node. //! All attributes after and including the specified attribute are moved one // position back. //! \param where Place where to insert the attribute, or 0 to insert at the // back. //! \param attribute Attribute to insert. void insert_attribute(xml_attribute *where, xml_attribute *attribute) { assert(!where || where->parent() == this); assert(attribute && !attribute->parent()); if (where == m_first_attribute) prepend_attribute(attribute); else if (where == 0) append_attribute(attribute); else { attribute->m_prev_attribute = where->m_prev_attribute; attribute->m_next_attribute = where; where->m_prev_attribute->m_next_attribute = attribute; where->m_prev_attribute = attribute; attribute->m_parent = this; } } //! Removes first attribute of the node. //! If node has no attributes, behaviour is undefined. //! Use first_attribute() to test if node has attributes. void remove_first_attribute() { assert(first_attribute()); xml_attribute *attribute = m_first_attribute; if (attribute->m_next_attribute) { attribute->m_next_attribute->m_prev_attribute = 0; } else m_last_attribute = 0; attribute->m_parent = 0; m_first_attribute = attribute->m_next_attribute; } //! Removes last attribute of the node. //! If node has no attributes, behaviour is undefined. //! Use first_attribute() to test if node has attributes. void remove_last_attribute() { assert(first_attribute()); xml_attribute *attribute = m_last_attribute; if (attribute->m_prev_attribute) { attribute->m_prev_attribute->m_next_attribute = 0; m_last_attribute = attribute->m_prev_attribute; } else m_first_attribute = 0; attribute->m_parent = 0; } //! Removes specified attribute from node. //! \param where Pointer to attribute to be removed. void remove_attribute(xml_attribute *where) { assert(first_attribute() && where->parent() == this); if (where == m_first_attribute) remove_first_attribute(); else if (where == m_last_attribute) remove_last_attribute(); else { where->m_prev_attribute->m_next_attribute = where->m_next_attribute; where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; where->m_parent = 0; } } //! Removes all attributes of node. void remove_all_attributes() { for (xml_attribute *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) attribute->m_parent = 0; m_first_attribute = 0; } private: /////////////////////////////////////////////////////////////////////////// // Restrictions // No copying xml_node(const xml_node &); void operator=(const xml_node &); /////////////////////////////////////////////////////////////////////////// // Data members // Note that some of the pointers below have UNDEFINED values if certain // other pointers are 0. // This is required for maximum performance, as it allows the parser to omit // initialization of // unneded/redundant values. // // The rules are as follows: // 1. first_node and first_attribute contain valid pointers, or 0 if node // has no children/attributes respectively // 2. last_node and last_attribute are valid only if node has at least one // child/attribute respectively, otherwise they contain garbage // 3. prev_sibling and next_sibling are valid only if node has a parent, // otherwise they contain garbage node_type m_type; // Type of node; always valid xml_node *m_first_node; // Pointer to first child node, or 0 if none; // always valid xml_node *m_last_node; // Pointer to last child node, or 0 if none; // this value is only valid if m_first_node is // non-zero xml_attribute *m_first_attribute; // Pointer to first attribute of // node, or 0 if none; always valid xml_attribute *m_last_attribute; // Pointer to last attribute of node, // or 0 if none; this value is only // valid if m_first_attribute is // non-zero xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 // if none; this value is only valid if // m_parent is non-zero xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if // none; this value is only valid if m_parent // is non-zero }; /////////////////////////////////////////////////////////////////////////// // XML document //! This class represents root of the DOM hierarchy. //! It is also an xml_node and a memory_pool through public inheritance. //! Use parse() function to build a DOM tree from a zero-terminated XML text // string. //! parse() function allocates memory for nodes and attributes by using // functions of xml_document, //! which are inherited from memory_pool. //! To access root node of the document, use the document itself, as if it was // an xml_node. //! \param Ch Character type to use. template class xml_document : public xml_node, public memory_pool { public: //! Constructs empty XML document xml_document() : xml_node(node_document) {} //! Parses zero-terminated XML string according to given flags. //! Passed string will be modified by the parser, unless // rapidxml::parse_non_destructive flag is used. //! The string must persist for the lifetime of the document. //! In case of error, rapidxml::parse_error exception will be thrown. //!

//! If you want to parse contents of a file, you must first load the file // into the memory, and pass pointer to its beginning. //! Make sure that data is zero-terminated. //!

//! Document can be parsed into multiple times. //! Each new call to parse removes previous nodes and attributes (if any), // but does not clear memory pool. //! \param text XML data to parse; pointer is non-const to denote fact that // this data may be modified by the parser. template void parse(Ch *text) { assert(text); // Remove current contents this->remove_all_nodes(); this->remove_all_attributes(); // Parse BOM, if any parse_bom(text); // Parse children while (1) { // Skip whitespace before node skip(text); if (*text == 0) break; // Parse and append new child if (*text == Ch('<')) { ++text; // Skip '<' if (xml_node *node = parse_node(text)) this->append_node(node); } else RAPIDXML_PARSE_ERROR("expected <", text); } } //! Clears the document by deleting all nodes and clearing the memory pool. //! All nodes owned by document pool are destroyed. void clear() { this->remove_all_nodes(); this->remove_all_attributes(); memory_pool::clear(); } private: /////////////////////////////////////////////////////////////////////// // Internal character utility functions // Detect whitespace character struct whitespace_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_whitespace [static_cast(ch)]; } }; // Detect node name character struct node_name_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_node_name [static_cast(ch)]; } }; // Detect attribute name character struct attribute_name_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_attribute_name [static_cast(ch)]; } }; // Detect text character (PCDATA) struct text_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_text [static_cast(ch)]; } }; // Detect text character (PCDATA) that does not require processing struct text_pure_no_ws_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_text_pure_no_ws [static_cast(ch)]; } }; // Detect text character (PCDATA) that does not require processing struct text_pure_with_ws_pred { static unsigned char test(Ch ch) { return internal::lookup_tables<0>::lookup_text_pure_with_ws [static_cast(ch)]; } }; // Detect attribute value character template struct attribute_value_pred { static unsigned char test(Ch ch) { if (Quote == Ch('\'')) return internal::lookup_tables<0>::lookup_attribute_data_1 [static_cast(ch)]; if (Quote == Ch('\"')) return internal::lookup_tables<0>::lookup_attribute_data_2 [static_cast(ch)]; return 0; // Should never be executed, to avoid warnings on Comeau } }; // Detect attribute value character template struct attribute_value_pure_pred { static unsigned char test(Ch ch) { if (Quote == Ch('\'')) return internal::lookup_tables<0>::lookup_attribute_data_1_pure [static_cast(ch)]; if (Quote == Ch('\"')) return internal::lookup_tables<0>::lookup_attribute_data_2_pure [static_cast(ch)]; return 0; // Should never be executed, to avoid warnings on Comeau } }; // Insert coded character, using UTF8 or 8-bit ASCII template static void insert_coded_character(Ch *&text, unsigned long code) { if (Flags & parse_no_utf8) { // Insert 8-bit ASCII character // Todo: possibly verify that code is less than 256 and use replacement // char otherwise? text[0] = static_cast(code); text += 1; } else { // Insert UTF8 sequence if (code < 0x80) // 1 byte sequence { text[0] = static_cast(code); text += 1; } else if (code < 0x800) // 2 byte sequence { text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[0] = static_cast(code | 0xC0); text += 2; } else if (code < 0x10000) // 3 byte sequence { text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[0] = static_cast(code | 0xE0); text += 3; } else if (code < 0x110000) // 4 byte sequence { text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; text[0] = static_cast(code | 0xF0); text += 4; } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode { RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); } } } // Skip characters until predicate evaluates to true template static void skip(Ch *&text) { Ch *tmp = text; while (StopPred::test(*tmp)) ++tmp; text = tmp; } // Skip characters until predicate evaluates to true while doing the // following: // - replacing XML character entity references with proper characters // (' & " < > &#...;) // - condensing whitespace sequences to single space character template static Ch *skip_and_expand_character_refs(Ch *&text) { // If entity translation, whitespace condense and whitespace trimming is // disabled, use plain skip if (Flags & parse_no_entity_translation && !(Flags & parse_normalize_whitespace) && !(Flags & parse_trim_whitespace)) { skip(text); return text; } // Use simple skip until first modification is detected skip(text); // Use translation skip Ch *src = text; Ch *dest = src; while (StopPred::test(*src)) { // If entity translation is enabled if (!(Flags & parse_no_entity_translation)) { // Test if replacement is needed if (src[0] == Ch('&')) { switch (src[1]) { // & ' case Ch('a') : if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { *dest = Ch('&'); ++dest; src += 5; continue; } if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) { *dest = Ch('\''); ++dest; src += 6; continue; } break; // " case Ch('q') : if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) { *dest = Ch('"'); ++dest; src += 6; continue; } break; // > case Ch('g') : if (src[2] == Ch('t') && src[3] == Ch(';')) { *dest = Ch('>'); ++dest; src += 4; continue; } break; // < case Ch('l') : if (src[2] == Ch('t') && src[3] == Ch(';')) { *dest = Ch('<'); ++dest; src += 4; continue; } break; // &#...; - assumes ASCII case Ch('#') : if (src[2] == Ch('x')) { unsigned long code = 0; src += 3; // Skip &#x while (1) { unsigned char digit = internal::lookup_tables<0>::lookup_digits [static_cast(*src)]; if (digit == 0xFF) break; code = code * 16 + digit; ++src; } insert_coded_character(dest, code); // Put character in output } else { unsigned long code = 0; src += 2; // Skip &# while (1) { unsigned char digit = internal::lookup_tables<0>::lookup_digits [static_cast(*src)]; if (digit == 0xFF) break; code = code * 10 + digit; ++src; } insert_coded_character(dest, code); // Put character in output } if (*src == Ch(';')) ++src; else RAPIDXML_PARSE_ERROR("expected ;", src); continue; // Something else default: // Ignore, just copy '&' verbatim break; } } } // If whitespace condensing is enabled if (Flags & parse_normalize_whitespace) { // Test if condensing is needed if (whitespace_pred::test(*src)) { *dest = Ch(' '); ++dest; // Put single space in dest ++src; // Skip first whitespace char // Skip remaining whitespace chars while (whitespace_pred::test(*src)) ++src; continue; } } // No replacement, only copy character *dest++ = *src++; } // Return new end text = src; return dest; } /////////////////////////////////////////////////////////////////////// // Internal parsing functions // Parse BOM, if any template void parse_bom(Ch *&text) { // UTF-8? if (static_cast(text[0]) == 0xEF && static_cast(text[1]) == 0xBB && static_cast(text[2]) == 0xBF) { text += 3; // Skup utf-8 bom } } // Parse XML declaration ( xml_node *parse_xml_declaration(Ch *&text) { // If parsing of declaration is disabled if (!(Flags & parse_declaration_node)) { // Skip until end of declaration while (text[0] != Ch('?') || text[1] != Ch('>')) { if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' return 0; } // Create declaration xml_node *declaration = this->allocate_node(node_declaration); // Skip whitespace before attributes or ?> skip(text); // Parse declaration attributes parse_node_attributes(text, declaration); // Skip ?> if (text[0] != Ch('?') || text[1] != Ch('>')) RAPIDXML_PARSE_ERROR("expected ?>", text); text += 2; return declaration; } // Parse XML comment (' return 0; // Do not produce comment node } // Remember value start Ch *value = text; // Skip until end of comment while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Create comment node xml_node *comment = this->allocate_node(node_comment); comment->value(value, text - value); // Place zero terminator after comment value if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); text += 3; // Skip '-->' return comment; } // Parse DOCTYPE template xml_node *parse_doctype(Ch *&text) { // Remember value start Ch *value = text; // Skip to > while (*text != Ch('>')) { // Determine character type switch (*text) { // If '[' encountered, scan for matching ending ']' using naive // algorithm with depth // This works for all W3C test files except for 2 most wicked case Ch('[') : { ++text; // Skip '[' int depth = 1; while (depth > 0) { switch (*text) { case Ch('[') : ++depth; break; case Ch(']') : --depth; break; case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); } ++text; } break; } // Error on end of text case Ch('\0') : RAPIDXML_PARSE_ERROR("unexpected end of data", text); // Other character, skip it default: ++text; } } // If DOCTYPE nodes enabled if (Flags & parse_doctype_node) { // Create a new doctype node xml_node *doctype = this->allocate_node(node_doctype); doctype->value(value, text - value); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); text += 1; // skip '>' return doctype; } else { text += 1; // skip '>' return 0; } } // Parse PI template xml_node *parse_pi(Ch *&text) { // If creation of PI nodes is enabled if (Flags & parse_pi_nodes) { // Create pi node xml_node *pi = this->allocate_node(node_pi); // Extract PI target name Ch *name = text; skip(text); if (text == name) RAPIDXML_PARSE_ERROR("expected PI target", text); pi->name(name, text - name); // Skip whitespace between pi target and pi skip(text); // Remember start of pi Ch *value = text; // Skip to '?>' while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Set pi value (verbatim, no entity expansion or whitespace // normalization) pi->value(value, text - value); // Place zero terminator after name and value if (!(Flags & parse_no_string_terminators)) { pi->name()[pi->name_size()] = Ch('\0'); pi->value()[pi->value_size()] = Ch('\0'); } text += 2; // Skip '?>' return pi; } else { // Skip to '?>' while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' return 0; } } // Parse and append data // Return character that ends data. // This is necessary because this character might have been overwritten by a // terminating 0 template Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { // Backup to contents start if whitespace trimming is disabled if (!(Flags & parse_trim_whitespace)) text = contents_start; // Skip until end of data Ch *value = text, *end; if (Flags & parse_normalize_whitespace) end = skip_and_expand_character_refs(text); else end = skip_and_expand_character_refs(text); // Trim trailing whitespace if flag is set; leading was already trimmed by // whitespace skip after > if (Flags & parse_trim_whitespace) { if (Flags & parse_normalize_whitespace) { // Whitespace is already condensed to single space characters by // skipping function, so just trim 1 char off the end if (*(end - 1) == Ch(' ')) --end; } else { // Backup until non-whitespace character is found while (whitespace_pred::test(*(end - 1))) --end; } } // If characters are still left between end and value (this test is only // necessary if normalization is enabled) // Create new data node if (!(Flags & parse_no_data_nodes)) { xml_node *data = this->allocate_node(node_data); data->value(value, end - value); node->append_node(data); } // Add data to parent node if no data exists yet if (!(Flags & parse_no_element_values)) if (*node->value() == Ch('\0')) node->value(value, end - value); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) { Ch ch = *text; *end = Ch('\0'); return ch; // Return character that ends data; this is required because // zero terminator overwritten it } // Return character that ends data return *text; } // Parse CDATA template xml_node *parse_cdata(Ch *&text) { // If CDATA is disabled if (Flags & parse_no_data_nodes) { // Skip until end of cdata while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 3; // Skip ]]> return 0; // Do not produce CDATA node } // Skip until end of cdata Ch *value = text; while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Create new cdata node xml_node *cdata = this->allocate_node(node_cdata); cdata->value(value, text - value); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); text += 3; // Skip ]]> return cdata; } // Parse element node template xml_node *parse_element(Ch *&text) { // Create element node xml_node *element = this->allocate_node(node_element); // Extract element name Ch *name = text; skip(text); if (text == name) RAPIDXML_PARSE_ERROR("expected element name", text); element->name(name, text - name); // Skip whitespace between element name and attributes or > skip(text); // Parse attributes, if any parse_node_attributes(text, element); // Determine ending type if (*text == Ch('>')) { ++text; parse_node_contents(text, element); } else if (*text == Ch('/')) { ++text; if (*text != Ch('>')) RAPIDXML_PARSE_ERROR("expected >", text); ++text; } else RAPIDXML_PARSE_ERROR("expected >", text); // Place zero terminator after name if (!(Flags & parse_no_string_terminators)) element->name()[element->name_size()] = Ch('\0'); // Return parsed element return element; } // Determine node type, and parse it template xml_node *parse_node(Ch *&text) { // Parse proper node type switch (text[0]) { // <... default: // Parse and append element node return parse_element(text); // (text); } else { // Parse PI return parse_pi(text); } // (text); } break; // (text); } break; // (text); } } // switch // Attempt to skip other, unrecognized node types starting with ')) { if (*text == 0) RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } ++text; // Skip '>' return 0; // No node recognized } } // Parse contents of the node - children, data etc. template void parse_node_contents(Ch *&text, xml_node *node) { // For all children and text while (1) { // Skip whitespace between > and node contents Ch *contents_start = text; // Store start of node contents before whitespace is skipped skip(text); Ch next_char = *text; // After data nodes, instead of continuing the loop, control jumps here. // This is because zero termination inside parse_and_append_data() // function // would wreak havoc with the above code. // Also, skipping whitespace after data nodes is unnecessary. after_data_node: // Determine what comes next: node closing, child node, data node, or 0? switch (next_char) { // Node closing or child node case Ch('<') : if (text[1] == Ch('/')) { // Node closing text += 2; // Skip '(text); if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) RAPIDXML_PARSE_ERROR("invalid closing tag name", text); } else { // No validation, just skip name skip(text); } // Skip remaining whitespace after node name skip(text); if (*text != Ch('>')) RAPIDXML_PARSE_ERROR("expected >", text); ++text; // Skip '>' return; // Node closed, finished parsing contents } else { // Child node ++text; // Skip '<' if (xml_node *child = parse_node(text)) node->append_node(child); } break; // End of data - error case Ch('\0') : RAPIDXML_PARSE_ERROR("unexpected end of data", text); // Data node default: next_char = parse_and_append_data(node, text, contents_start); goto after_data_node; // Bypass regular processing after data nodes } } } // Parse XML attributes of the node template void parse_node_attributes(Ch *&text, xml_node *node) { // For all attributes while (attribute_name_pred::test(*text)) { // Extract attribute name Ch *name = text; ++text; // Skip first character of attribute name skip(text); if (text == name) RAPIDXML_PARSE_ERROR("expected attribute name", name); // Create new attribute xml_attribute *attribute = this->allocate_attribute(); attribute->name(name, text - name); node->append_attribute(attribute); // Skip whitespace after attribute name skip(text); // Skip = if (*text != Ch('=')) RAPIDXML_PARSE_ERROR("expected =", text); ++text; // Add terminating zero after name if (!(Flags & parse_no_string_terminators)) attribute->name()[attribute->name_size()] = 0; // Skip whitespace after = skip(text); // Skip quote and remember if it was ' or " Ch quote = *text; if (quote != Ch('\'') && quote != Ch('"')) RAPIDXML_PARSE_ERROR("expected ' or \"", text); ++text; // Extract attribute value and expand char refs in it Ch *value = text, *end; const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization // in attributes if (quote == Ch('\'')) end = skip_and_expand_character_refs< attribute_value_pred, attribute_value_pure_pred, AttFlags>(text); else end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); // Set attribute value attribute->value(value, end - value); // Make sure that end quote is present if (*text != quote) RAPIDXML_PARSE_ERROR("expected ' or \"", text); ++text; // Skip quote // Add terminating zero after value if (!(Flags & parse_no_string_terminators)) attribute->value()[attribute->value_size()] = 0; // Skip whitespace after attribute value skip(text); } } }; //! \cond internal namespace internal { // Whitespace (space \n \r \t) template const unsigned char lookup_tables::lookup_whitespace[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F }; // Node name (anything but space \n \r \t / > ? \0) template const unsigned char lookup_tables::lookup_node_name[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Text (i.e. PCDATA) (anything but < \0) template const unsigned char lookup_tables::lookup_text[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Text (i.e. PCDATA) that does not require processing when ws normalization // is disabled // (anything but < \0 &) template const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Text (i.e. PCDATA) that does not require processing when ws // normalizationis is enabled // (anything but < \0 & space \n \r \t) template const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Attribute name (anything but space \n \r \t / < > = ? ! \0) template const unsigned char lookup_tables::lookup_attribute_name[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Attribute data with single quote (anything but ' \0) template const unsigned char lookup_tables::lookup_attribute_data_1[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Attribute data with single quote that does not require processing // (anything but ' \0 &) template const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Attribute data with double quote (anything but " \0) template const unsigned char lookup_tables::lookup_attribute_data_2[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Attribute data with double quote that does not require processing // (anything but " \0 &) template const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F }; // Digits (dec and hex, 255 denotes end of numeric character reference) template const unsigned char lookup_tables::lookup_digits[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 1 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 2 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, // 3 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 4 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 5 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 6 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 7 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 8 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 9 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // A 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // B 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // C 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // D 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // E 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 // F }; // Upper case conversion template const unsigned char lookup_tables::lookup_upcase[256] = { // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, // 7 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 8 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 9 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // A 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // B 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // C 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // D 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // E 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // F }; } //! \endcond } // Undefine internal macros #undef RAPIDXML_PARSE_ERROR // On MSVC, restore warnings state #ifdef _MSC_VER #pragma warning(pop) #endif #endif cpp-netlib-0.11.2-final/libs/network/example/rapidxml/rapidxml_iterators.hpp000066400000000000000000000056551256751517300272700ustar00rootroot00000000000000#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED #define RAPIDXML_ITERATORS_HPP_INCLUDED // Copyright (C) 2006, 2009 Marcin Kalicinski // Version 1.13 // Revision $DateTime: 2009/05/13 01:46:17 $ //! \file rapidxml_iterators.hpp This file contains rapidxml iterators #include "rapidxml.hpp" namespace rapidxml { //! Iterator of child nodes of xml_node template class node_iterator { public: typedef typename xml_node value_type; typedef typename xml_node &reference; typedef typename xml_node *pointer; typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; node_iterator() : m_node(0) {} node_iterator(xml_node *node) : m_node(node->first_node()) {} reference operator*() const { assert(m_node); return *m_node; } pointer operator->() const { assert(m_node); return m_node; } node_iterator &operator++() { assert(m_node); m_node = m_node->next_sibling(); return *this; } node_iterator operator++(int) { node_iterator tmp = *this; ++this; return tmp; } node_iterator &operator--() { assert(m_node && m_node->previous_sibling()); m_node = m_node->previous_sibling(); return *this; } node_iterator operator--(int) { node_iterator tmp = *this; ++this; return tmp; } bool operator==(const node_iterator &rhs) { return m_node == rhs.m_node; } bool operator!=(const node_iterator &rhs) { return m_node != rhs.m_node; } private: xml_node *m_node; }; //! Iterator of child attributes of xml_node template class attribute_iterator { public: typedef typename xml_attribute value_type; typedef typename xml_attribute &reference; typedef typename xml_attribute *pointer; typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; attribute_iterator() : m_attribute(0) {} attribute_iterator(xml_node *node) : m_attribute(node->first_attribute()) {} reference operator*() const { assert(m_attribute); return *m_attribute; } pointer operator->() const { assert(m_attribute); return m_attribute; } attribute_iterator &operator++() { assert(m_attribute); m_attribute = m_attribute->next_attribute(); return *this; } attribute_iterator operator++(int) { attribute_iterator tmp = *this; ++this; return tmp; } attribute_iterator &operator--() { assert(m_attribute && m_attribute->previous_attribute()); m_attribute = m_attribute->previous_attribute(); return *this; } attribute_iterator operator--(int) { attribute_iterator tmp = *this; ++this; return tmp; } bool operator==(const attribute_iterator &rhs) { return m_attribute == rhs.m_attribute; } bool operator!=(const attribute_iterator &rhs) { return m_attribute != rhs.m_attribute; } private: xml_attribute *m_attribute; }; } #endif cpp-netlib-0.11.2-final/libs/network/example/rapidxml/rapidxml_print.hpp000066400000000000000000000310211256751517300263720ustar00rootroot00000000000000#ifndef RAPIDXML_PRINT_HPP_INCLUDED #define RAPIDXML_PRINT_HPP_INCLUDED // Copyright (C) 2006, 2009 Marcin Kalicinski // Version 1.13 // Revision $DateTime: 2009/05/13 01:46:17 $ //! \file rapidxml_print.hpp This file contains rapidxml printer implementation #include "rapidxml.hpp" // Only include streams if not disabled #ifndef RAPIDXML_NO_STREAMS #include #include #endif namespace rapidxml { /////////////////////////////////////////////////////////////////////// // Printing flags const int print_no_indenting = 0x1; //!< Printer flag instructing the printer // to suppress indenting of XML. See // print() function. /////////////////////////////////////////////////////////////////////// // Internal //! \cond internal namespace internal { /////////////////////////////////////////////////////////////////////////// // Internal character operations // Copy characters from given range to given output iterator template inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) { while (begin != end) *out++ = *begin++; return out; } // Copy characters from given range to given output iterator and expand // characters into references (< > ' " &) template inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) { while (begin != end) { if (*begin == noexpand) { *out++ = *begin; // No expansion, copy character } else { switch (*begin) { case Ch('<') : *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); break; case Ch('>') : *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); break; case Ch('\'') : *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); break; case Ch('"') : *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); break; case Ch('&') : *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); break; default: *out++ = *begin; // No expansion, copy character } } ++begin; // Step to next character } return out; } // Fill given output iterator with repetitions of the same character template inline OutIt fill_chars(OutIt out, int n, Ch ch) { for (int i = 0; i < n; ++i) *out++ = ch; return out; } // Find character template inline bool find_char(const Ch *begin, const Ch *end) { while (begin != end) if (*begin++ == ch) return true; return false; } /////////////////////////////////////////////////////////////////////////// // Internal printing operations // Print node template inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) { // Print proper node type switch (node->type()) { // Document case node_document: out = print_children(out, node, flags, indent); break; // Element case node_element: out = print_element_node(out, node, flags, indent); break; // Data case node_data: out = print_data_node(out, node, flags, indent); break; // CDATA case node_cdata: out = print_cdata_node(out, node, flags, indent); break; // Declaration case node_declaration: out = print_declaration_node(out, node, flags, indent); break; // Comment case node_comment: out = print_comment_node(out, node, flags, indent); break; // Doctype case node_doctype: out = print_doctype_node(out, node, flags, indent); break; // Pi case node_pi: out = print_pi_node(out, node, flags, indent); break; // Unknown default: assert(0); break; } // If indenting not disabled, add line break after node if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; // Return modified iterator return out; } // Print children of the node template inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) { for (xml_node *child = node->first_node(); child; child = child->next_sibling()) out = print_node(out, child, flags, indent); return out; } // Print attributes of the node template inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) { for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) { if (attribute->name() && attribute->value()) { // Print attribute name *out = Ch(' '), ++out; out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); *out = Ch('='), ++out; // Print attribute value using appropriate quote type if (find_char( attribute->value(), attribute->value() + attribute->value_size())) { *out = Ch('\''), ++out; out = copy_and_expand_chars( attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); *out = Ch('\''), ++out; } else { *out = Ch('"'), ++out; out = copy_and_expand_chars( attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); *out = Ch('"'), ++out; } } } return out; } // Print data node template inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_data); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); return out; } // Print data node template inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_cdata); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'); ++out; *out = Ch('!'); ++out; *out = Ch('['); ++out; *out = Ch('C'); ++out; *out = Ch('D'); ++out; *out = Ch('A'); ++out; *out = Ch('T'); ++out; *out = Ch('A'); ++out; *out = Ch('['); ++out; out = copy_chars(node->value(), node->value() + node->value_size(), out); *out = Ch(']'); ++out; *out = Ch(']'); ++out; *out = Ch('>'); ++out; return out; } // Print element node template inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_element); // Print element name and attributes, if any if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'), ++out; out = copy_chars(node->name(), node->name() + node->name_size(), out); out = print_attributes(out, node, flags); // If node is childless if (node->value_size() == 0 && !node->first_node()) { // Print childless node tag ending *out = Ch('/'), ++out; *out = Ch('>'), ++out; } else { // Print normal node tag ending *out = Ch('>'), ++out; // Test if node contains a single data node only (and no other nodes) xml_node *child = node->first_node(); if (!child) { // If node has no children, only print its value without indenting out = copy_and_expand_chars( node->value(), node->value() + node->value_size(), Ch(0), out); } else if (child->next_sibling() == 0 && child->type() == node_data) { // If node has a sole data child, only print its value without // indenting out = copy_and_expand_chars( child->value(), child->value() + child->value_size(), Ch(0), out); } else { // Print all children with full indenting if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; out = print_children(out, node, flags, indent + 1); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); } // Print node end *out = Ch('<'), ++out; *out = Ch('/'), ++out; out = copy_chars(node->name(), node->name() + node->name_size(), out); *out = Ch('>'), ++out; } return out; } // Print declaration node template inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) { // Print declaration start if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'), ++out; *out = Ch('?'), ++out; *out = Ch('x'), ++out; *out = Ch('m'), ++out; *out = Ch('l'), ++out; // Print attributes out = print_attributes(out, node, flags); // Print declaration end *out = Ch('?'), ++out; *out = Ch('>'), ++out; return out; } // Print comment node template inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_comment); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'), ++out; *out = Ch('!'), ++out; *out = Ch('-'), ++out; *out = Ch('-'), ++out; out = copy_chars(node->value(), node->value() + node->value_size(), out); *out = Ch('-'), ++out; *out = Ch('-'), ++out; *out = Ch('>'), ++out; return out; } // Print doctype node template inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_doctype); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'), ++out; *out = Ch('!'), ++out; *out = Ch('D'), ++out; *out = Ch('O'), ++out; *out = Ch('C'), ++out; *out = Ch('T'), ++out; *out = Ch('Y'), ++out; *out = Ch('P'), ++out; *out = Ch('E'), ++out; *out = Ch(' '), ++out; out = copy_chars(node->value(), node->value() + node->value_size(), out); *out = Ch('>'), ++out; return out; } // Print pi node template inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) { assert(node->type() == node_pi); if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); *out = Ch('<'), ++out; *out = Ch('?'), ++out; out = copy_chars(node->name(), node->name() + node->name_size(), out); *out = Ch(' '), ++out; out = copy_chars(node->value(), node->value() + node->value_size(), out); *out = Ch('?'), ++out; *out = Ch('>'), ++out; return out; } } //! \endcond /////////////////////////////////////////////////////////////////////////// // Printing //! Prints XML to given output iterator. //! \param out Output iterator to print to. //! \param node Node to be printed. Pass xml_document to print entire // document. //! \param flags Flags controlling how XML is printed. //! \return Output iterator pointing to position immediately after last // character of printed text. template inline OutIt print(OutIt out, const xml_node &node, int flags = 0) { return internal::print_node(out, &node, flags, 0); } #ifndef RAPIDXML_NO_STREAMS //! Prints XML to given output stream. //! \param out Output stream to print to. //! \param node Node to be printed. Pass xml_document to print entire // document. //! \param flags Flags controlling how XML is printed. //! \return Output stream. template inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) { print(std::ostream_iterator(out), node, flags); return out; } //! Prints formatted XML to given output stream. Uses default printing flags. // Use print() function to customize printing process. //! \param out Output stream to print to. //! \param node Node to be printed. //! \return Output stream. template inline std::basic_ostream &operator<<(std::basic_ostream &out, const xml_node &node) { return print(out, node); } #endif } #endif cpp-netlib-0.11.2-final/libs/network/example/rapidxml/rapidxml_utils.hpp000066400000000000000000000053741256751517300264120ustar00rootroot00000000000000#ifndef RAPIDXML_UTILS_HPP_INCLUDED #define RAPIDXML_UTILS_HPP_INCLUDED // Copyright (C) 2006, 2009 Marcin Kalicinski // Version 1.13 // Revision $DateTime: 2009/05/13 01:46:17 $ //! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities // that can be useful //! in certain simple scenarios. They should probably not be used if maximizing // performance is the main objective. #include "rapidxml.hpp" #include #include #include #include namespace rapidxml { //! Represents data loaded from a file template class file { public: //! Loads file into the memory. Data will be automatically destroyed by the // destructor. //! \param filename Filename to load. file(const char *filename) { using namespace std; // Open stream basic_ifstream stream(filename, ios::binary); if (!stream) throw runtime_error(string("cannot open file ") + filename); stream.unsetf(ios::skipws); // Determine stream size stream.seekg(0, ios::end); size_t size = stream.tellg(); stream.seekg(0); // Load data and add terminating 0 m_data.resize(size + 1); stream.read(&m_data.front(), static_cast(size)); m_data[size] = 0; } //! Loads file into the memory. Data will be automatically destroyed by the // destructor //! \param stream Stream to load from file(std::basic_istream &stream) { using namespace std; // Load data and add terminating 0 stream.unsetf(ios::skipws); m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); if (stream.fail() || stream.bad()) throw runtime_error("error reading stream"); m_data.push_back(0); } //! Gets file data. //! \return Pointer to data of file. Ch *data() { return &m_data.front(); } //! Gets file data. //! \return Pointer to data of file. const Ch *data() const { return &m_data.front(); } //! Gets file data size. //! \return Size of file data, in characters. std::size_t size() const { return m_data.size(); } private: std::vector m_data; // File data }; //! Counts children of node. Time complexity is O(n). //! \return Number of children of node template inline std::size_t count_children(xml_node *node) { xml_node *child = node->first_node(); std::size_t count = 0; while (child) { ++count; child = child->next_sibling(); } return count; } //! Counts attributes of node. Time complexity is O(n). //! \return Number of attributes of node template inline std::size_t count_attributes(xml_node *node) { xml_attribute *attr = node->first_attribute(); std::size_t count = 0; while (attr) { ++count; attr = attr->next_attribute(); } return count; } } #endif cpp-netlib-0.11.2-final/libs/network/example/rss/000077500000000000000000000000001256751517300216175ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/rss/main.cpp000066400000000000000000000020611256751517300232460ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "rss.hpp" #include #include #include int main(int argc, char *argv[]) { using namespace boost::network; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } try { http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); rss::channel channel(response); std::cout << "Channel: " << channel.title() << " (" << channel.description() << ")" << std::endl; BOOST_FOREACH(const rss::item & item, channel) { std::cout << item.title() << " (" << item.author() << ")" << std::endl; } } catch (std::exception &e) { std::cerr << e.what() << std::endl; } return 0; } cpp-netlib-0.11.2-final/libs/network/example/rss/rss.cpp000066400000000000000000000037771256751517300231500ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "rss.hpp" #include "../rapidxml/rapidxml.hpp" #include #include namespace boost { namespace network { namespace rss { channel::channel(const http::client::response &response) { std::string response_body = body(response); rapidxml::xml_document<> doc; doc.parse<0>(const_cast(response_body.c_str())); rapidxml::xml_node<> *rss = doc.first_node("rss"); if (!rss) { throw std::runtime_error("Invalid RSS feed."); } rapidxml::xml_node<> *channel = rss->first_node("channel"); if (!channel) { throw std::runtime_error("Invalid RSS channel."); } rapidxml::xml_node<> *title = channel->first_node("title"); if (title) { title_ = title->first_node()->value(); } rapidxml::xml_node<> *description = channel->first_node("description"); if (description) { description_ = description->first_node()->value(); } rapidxml::xml_node<> *link = channel->first_node("link"); if (link) { link_ = link->first_node()->value(); } rapidxml::xml_node<> *author = channel->first_node("author"); if (author) { author_ = author->first_node()->value(); } rapidxml::xml_node<> *item = channel->first_node("item"); while (item) { items_.push_back(rss::item()); rapidxml::xml_node<> *title = item->first_node("title"); if (title) { items_.back().set_title(title->first_node()->value()); } rapidxml::xml_node<> *author = item->first_node("author"); if (author) { items_.back().set_author(author->first_node()->value()); } rapidxml::xml_node<> *description = item->first_node("description"); if (description) { items_.back().set_description(description->first_node()->value()); } item = item->next_sibling(); } } } // namespace rss } // namespace network } // namespace boost cpp-netlib-0.11.2-final/libs/network/example/rss/rss.hpp000066400000000000000000000034051256751517300231410ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef ___RSS_INC__ #define ___RSS_INC__ #include #include #include namespace boost { namespace network { namespace rss { class item { public: void set_title(const std::string &title) { title_ = title; } std::string title() const { return title_; } void set_author(const std::string &author) { author_ = author; } std::string author() const { return author_; } void set_description(const std::string &description) { description_ = description; } std::string description() const { return description_; } private: std::string title_; std::string author_; std::string description_; }; class channel { public: typedef item value_type; typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; channel(const http::client::response &response); std::string title() const { return title_; } std::string description() const { return description_; } std::string link() const { return link_; } std::string author() const { return author_; } unsigned int item_count() const { return items_.size(); } iterator begin() { return items_.begin(); } iterator end() { return items_.end(); } const_iterator begin() const { return items_.begin(); } const_iterator end() const { return items_.end(); } private: std::string title_; std::string description_; std::string link_; std::string author_; std::vector items_; }; } // namespace rss } // namespace network } // namespace boost #endif // ___RSS_INC__ cpp-netlib-0.11.2-final/libs/network/example/simple_wget.cpp000066400000000000000000000030151256751517300240320ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2009, 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //[ simple_wget_main /*` This is a very basic clone of wget. It's missing a lot of features, such as content-type detection, but it does the fundamental things the same. It demonstrates the use the `uri` and the `http::client`. */ #include #include #include #include #include namespace http = boost::network::http; namespace uri = boost::network::uri; namespace { std::string get_filename(const uri::uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); return filename.empty() ? "index.html" : filename; } } // namespace int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " url" << std::endl; return 1; } http::client client; try { http::client::request request(argv[1]); http::client::response response = client.get(request); std::string filename = get_filename(request.uri()); std::cout << "Saving to: " << filename << std::endl; std::ofstream ofs(filename.c_str()); ofs << static_cast(body(response)) << std::endl; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } //] cpp-netlib-0.11.2-final/libs/network/example/trivial_google.cpp000066400000000000000000000010731256751517300245230ustar00rootroot00000000000000// Copyright 2014 Dean Michael Berris // Copyright 2014 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace http = boost::network::http; int main(int, char * []) { http::client client; http::client::request request("https://www.google.com/"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; } cpp-netlib-0.11.2-final/libs/network/example/twitter/000077500000000000000000000000001256751517300225125ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/000077500000000000000000000000001256751517300245035ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/document.h000066400000000000000000000704631256751517300265040ustar00rootroot00000000000000#ifndef RAPIDJSON_DOCUMENT_H_ #define RAPIDJSON_DOCUMENT_H_ #include "reader.h" #include "internal/strfunc.h" namespace rapidjson { /////////////////////////////////////////////////////////////////////////////// // GenericValue //! Represents a JSON value. Use Value for UTF8 encoding and default allocator. /*! A JSON value can be one of 7 types. This class is a variant type supporting these types. Use the Value if UTF8 and default allocator \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) \tparam Allocator Allocator type for allocating memory of object, array and string. */ #pragma pack (push, 4) template > class GenericValue { public: //! Name-value pair in an object. struct Member { GenericValue name; //!< name of member (must be a string) GenericValue value; //!< value of member. }; typedef Encoding EncodingType; //!< Encoding type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef Member* MemberIterator; //!< Member iterator for iterating in object. typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. //!@name Constructors and destructor. //@{ //! Default constructor creates a null value. GenericValue() : flags_(kNullFlag) {} //! Copy constructor is not permitted. private: GenericValue(const GenericValue& rhs); public: //! Constructor with JSON value type. /*! This creates a Value of specified type with default content. \param type Type of the value. \note Default content for number is zero. */ GenericValue(Type type) { static const unsigned defaultFlags[7] = { kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag }; RAPIDJSON_ASSERT(type <= kNumberType); flags_ = defaultFlags[type]; memset(&data_, 0, sizeof(data_)); } //! Constructor for boolean value. GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} //! Constructor for int value. GenericValue(int i) : flags_(kNumberIntFlag) { data_.n.i64 = i; if (i >= 0) flags_ |= kUintFlag | kUint64Flag; } //! Constructor for unsigned value. GenericValue(unsigned u) : flags_(kNumberUintFlag) { data_.n.u64 = u; if (!(u & 0x80000000)) flags_ |= kIntFlag | kInt64Flag; } //! Constructor for int64_t value. GenericValue(int64_t i64) : flags_(kNumberInt64Flag) { data_.n.i64 = i64; if (i64 >= 0) { flags_ |= kNumberUint64Flag; if (!(i64 & 0xFFFFFFFF00000000LL)) flags_ |= kUintFlag; if (!(i64 & 0xFFFFFFFF80000000LL)) flags_ |= kIntFlag; } else if (i64 >= -2147483648LL) flags_ |= kIntFlag; } //! Constructor for uint64_t value. GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) { data_.n.u64 = u64; if (!(u64 & 0x8000000000000000L)) flags_ |= kInt64Flag; if (!(u64 & 0xFFFFFFFF00000000L)) flags_ |= kUintFlag; if (!(u64 & 0xFFFFFFFF80000000L)) flags_ |= kIntFlag; } //! Constructor for double value. GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; } //! Constructor for constant string (i.e. do not make a copy of string) GenericValue(const Ch* s, SizeType length) { RAPIDJSON_ASSERT(s != NULL); flags_ = kConstStringFlag; data_.s.str = s; data_.s.length = length; } //! Constructor for constant string (i.e. do not make a copy of string) GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); } //! Constructor for copy-string (i.e. do make a copy of string) GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); } //! Constructor for copy-string (i.e. do make a copy of string) GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); } //! Destructor. /*! Need to destruct elements of array, members of object, or copy-string. */ ~GenericValue() { if (Allocator::kNeedFree) { // Shortcut by Allocator's trait switch(flags_) { case kArrayFlag: for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) v->~GenericValue(); Allocator::Free(data_.a.elements); break; case kObjectFlag: for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { m->name.~GenericValue(); m->value.~GenericValue(); } Allocator::Free(data_.o.members); break; case kCopyStringFlag: Allocator::Free((void*)data_.s.str); break; } } } //@} //!@name Assignment operators //@{ //! Assignment with move semantics. /*! \param rhs Source of the assignment. It will become a null value after assignment. */ GenericValue& operator=(GenericValue& rhs) { RAPIDJSON_ASSERT(this != &rhs); this->~GenericValue(); memcpy(this, &rhs, sizeof(GenericValue)); rhs.flags_ = kNullFlag; return *this; } //! Assignment with primitive types. /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch* \param value The value to be assigned. */ template GenericValue& operator=(T value) { this->~GenericValue(); new (this) GenericValue(value); return *this; } //@} //!@name Type //@{ Type GetType() const { return static_cast(flags_ & kTypeMask); } bool IsNull() const { return flags_ == kNullFlag; } bool IsFalse() const { return flags_ == kFalseFlag; } bool IsTrue() const { return flags_ == kTrueFlag; } bool IsBool() const { return (flags_ & kBoolFlag) != 0; } bool IsObject() const { return flags_ == kObjectFlag; } bool IsArray() const { return flags_ == kArrayFlag; } bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } bool IsInt() const { return (flags_ & kIntFlag) != 0; } bool IsUint() const { return (flags_ & kUintFlag) != 0; } bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } bool IsString() const { return (flags_ & kStringFlag) != 0; } //@} //!@name Null //@{ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } //@} //!@name Bool //@{ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } //@} //!@name Object //@{ //! Set this value as an empty object. GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } //! Get the value associated with the object's name. GenericValue& operator[](const Ch* name) { if (Member* member = FindMember(name)) return member->value; else { static GenericValue NullValue; return NullValue; } } const GenericValue& operator[](const Ch* name) const { return const_cast(*this)[name]; } //! Member iterators. ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } //! Check whether a member exists in the object. bool HasMember(const Ch* name) const { return FindMember(name) != 0; } //! Add a member (name-value pair) to the object. /*! \param name A string value as name of member. \param value Value of any type. \param allocator Allocator for reallocating memory. \return The value itself for fluent API. \note The ownership of name and value will be transfered to this object if success. */ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(name.IsString()); Object& o = data_.o; if (o.size >= o.capacity) { if (o.capacity == 0) { o.capacity = kDefaultObjectCapacity; o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member)); } else { SizeType oldCapacity = o.capacity; o.capacity *= 2; o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)); } } o.members[o.size].name = name; o.members[o.size].value = value; o.size++; return *this; } GenericValue& AddMember(const char* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) { GenericValue n(name, internal::StrLen(name), nameAllocator); return AddMember(n, value, allocator); } GenericValue& AddMember(const char* name, GenericValue& value, Allocator& allocator) { GenericValue n(name, internal::StrLen(name)); return AddMember(n, value, allocator); } template GenericValue& AddMember(const char* name, T value, Allocator& allocator) { GenericValue n(name, internal::StrLen(name)); GenericValue v(value); return AddMember(n, v, allocator); } //! Remove a member in object by its name. /*! \param name Name of member to be removed. \return Whether the member existed. \note Removing member is implemented by moving the last member. So the ordering of members is changed. */ bool RemoveMember(const Ch* name) { RAPIDJSON_ASSERT(IsObject()); if (Member* m = FindMember(name)) { RAPIDJSON_ASSERT(data_.o.size > 0); RAPIDJSON_ASSERT(data_.o.members != 0); if (data_.o.size > 1) { // Move the last one to this place Member* last = data_.o.members + (data_.o.size - 1); m->name = last->name; m->value = last->value; } else { // Only one left, just destroy m->name.~GenericValue(); m->value.~GenericValue(); } --data_.o.size; return true; } return false; } //@} //!@name Array //@{ //! Set this value as an empty array. GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } //! Get the number of elements in array. SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } //! Get the capacity of array. SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } //! Check whether the array is empty. bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } //! Remove all elements in the array. /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. */ void Clear() { RAPIDJSON_ASSERT(IsArray()); for (SizeType i = 0; i < data_.a.size; ++i) data_.a.elements[i].~GenericValue(); data_.a.size = 0; } //! Get an element from array by index. /*! \param index Zero-based index of element. \note \code Value a(kArrayType); a.PushBack(123); int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. int z = a[0u].GetInt(); // This works too. \endcode */ GenericValue& operator[](SizeType index) { RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(index < data_.a.size); return data_.a.elements[index]; } const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } //! Element iterator ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } ConstValueIterator Begin() const { return const_cast(*this).Begin(); } ConstValueIterator End() const { return const_cast(*this).End(); } //! Request the array to have enough capacity to store elements. /*! \param newCapacity The capacity that the array at least need to have. \param allocator The allocator for allocating memory. It must be the same one use previously. \return The value itself for fluent API. */ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { RAPIDJSON_ASSERT(IsArray()); if (newCapacity > data_.a.capacity) { data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); data_.a.capacity = newCapacity; } return *this; } //! Append a value at the end of the array. /*! \param value The value to be appended. \param allocator The allocator for allocating memory. It must be the same one use previously. \return The value itself for fluent API. \note The ownership of the value will be transfered to this object if success. \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. */ GenericValue& PushBack(GenericValue& value, Allocator& allocator) { RAPIDJSON_ASSERT(IsArray()); if (data_.a.size >= data_.a.capacity) Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator); data_.a.elements[data_.a.size++] = value; return *this; } template GenericValue& PushBack(T value, Allocator& allocator) { GenericValue v(value); return PushBack(v, allocator); } //! Remove the last element in the array. GenericValue& PopBack() { RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(!Empty()); data_.a.elements[--data_.a.size].~GenericValue(); return *this; } //@} //!@name Number //@{ int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i; } unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u; } int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } int64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.u64; } double GetDouble() const { RAPIDJSON_ASSERT(IsNumber()); if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. if ((flags_ & kIntFlag) != 0) return data_.n.i; // int -> double if ((flags_ & kUintFlag) != 0) return data_.n.u; // unsigned -> double if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) } GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } //@} //!@name String //@{ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; } //! Get the length of string. /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). */ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; } //! Set this value as a string without copying source string. /*! This version has better performance with supplied length, and also support string containing null character. \param s source string pointer. \param length The length of source string, excluding the trailing null terminator. \return The value itself for fluent API. */ GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; } //! Set this value as a string without copying source string. /*! \param s source string pointer. \return The value itself for fluent API. */ GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); } //! Set this value as a string by copying from source string. /*! This version has better performance with supplied length, and also support string containing null character. \param s source string. \param length The length of source string, excluding the trailing null terminator. \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). \return The value itself for fluent API. */ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; } //! Set this value as a string by copying from source string. /*! \param s source string. \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). \return The value itself for fluent API. */ GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; } //@} //! Generate events of this value to a Handler. /*! This function adopts the GoF visitor pattern. Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. It can also be used to deep clone this value via GenericDocument, which is also a Handler. \tparam Handler type of handler. \param handler An object implementing concept Handler. */ template GenericValue& Accept(Handler& handler) { switch(GetType()) { case kNullType: handler.Null(); break; case kFalseType: handler.Bool(false); break; case kTrueType: handler.Bool(true); break; case kObjectType: handler.StartObject(); for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { handler.String(m->name.data_.s.str, m->name.data_.s.length, false); m->value.Accept(handler); } handler.EndObject(data_.o.size); break; case kArrayType: handler.StartArray(); for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) v->Accept(handler); handler.EndArray(data_.a.size); break; case kStringType: handler.String(data_.s.str, data_.s.length, false); break; case kNumberType: if (IsInt()) handler.Int(data_.n.i); else if (IsUint()) handler.Uint(data_.n.u); else if (IsInt64()) handler.Int64(data_.n.i64); else if (IsUint64()) handler.Uint64(data_.n.i64); else handler.Double(data_.n.d); break; } return *this; } private: template friend class GenericDocument; enum { kBoolFlag = 0x100, kNumberFlag = 0x200, kIntFlag = 0x400, kUintFlag = 0x800, kInt64Flag = 0x1000, kUint64Flag = 0x2000, kDoubleFlag = 0x4000, kStringFlag = 0x100000, kCopyFlag = 0x200000, // Initial flags of different types. kNullFlag = kNullType, kTrueFlag = kTrueType | kBoolFlag, kFalseFlag = kFalseType | kBoolFlag, kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag, kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, kConstStringFlag = kStringType | kStringFlag, kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, kObjectFlag = kObjectType, kArrayFlag = kArrayType, kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler }; static const SizeType kDefaultArrayCapacity = 16; static const SizeType kDefaultObjectCapacity = 16; struct String { const Ch* str; SizeType length; unsigned hashcode; //!< reserved }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode // By using proper binary layout, retrieval of different integer types do not need conversions. union Number { #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN struct { int i; char padding[4]; }; struct { unsigned u; char padding2[4]; }; #else struct { char padding[4]; int i; }; struct { char padding2[4]; unsigned u; }; #endif int64_t i64; uint64_t u64; double d; }; // 8 bytes struct Object { Member* members; SizeType size; SizeType capacity; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode struct Array { GenericValue* elements; SizeType size; SizeType capacity; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode union Data { String s; Number n; Object o; Array a; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode //! Find member by name. Member* FindMember(const Ch* name) { RAPIDJSON_ASSERT(name); RAPIDJSON_ASSERT(IsObject()); Object& o = data_.o; for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) return member; return 0; } const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } // Initialize this value as array with initial data, without calling destructor. void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { flags_ = kArrayFlag; data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue)); memcpy(data_.a.elements, values, count * sizeof(GenericValue)); data_.a.size = data_.a.capacity = count; } //! Initialize this value as object with initial data, without calling destructor. void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) { flags_ = kObjectFlag; data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member)); memcpy(data_.o.members, members, count * sizeof(Member)); data_.o.size = data_.o.capacity = count; } //! Initialize this value as constant string, without calling destructor. void SetStringRaw(const Ch* s, SizeType length) { RAPIDJSON_ASSERT(s != NULL); flags_ = kConstStringFlag; data_.s.str = s; data_.s.length = length; } //! Initialize this value as copy string with initial data, without calling destructor. void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) { RAPIDJSON_ASSERT(s != NULL); flags_ = kCopyStringFlag; data_.s.str = (char *)allocator.Malloc(length + 1); data_.s.length = length; memcpy((void*)data_.s.str, s, length); ((char*)data_.s.str)[length] = '\0'; } //! Assignment without calling destructor void RawAssign(GenericValue& rhs) { memcpy(this, &rhs, sizeof(GenericValue)); rhs.flags_ = kNullFlag; } Data data_; unsigned flags_; }; #pragma pack (pop) //! Value with UTF8 encoding. typedef GenericValue > Value; /////////////////////////////////////////////////////////////////////////////// // GenericDocument //! A document for parsing JSON text as DOM. /*! \implements Handler \tparam Encoding encoding for both parsing and string storage. \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing. */ template > class GenericDocument : public GenericValue { public: typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. //! Constructor /*! \param allocator Optional allocator for allocating stack memory. \param stackCapacity Initial capacity of stack in bytes. */ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} //! Parse JSON text from an input stream. /*! \tparam parseFlags Combination of ParseFlag. \param stream Input stream to be parsed. \return The document itself for fluent API. */ template GenericDocument& ParseStream(Stream& stream) { ValueType::SetNull(); // Remove existing root if exist GenericReader reader; if (reader.template Parse(stream, *this)) { RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object this->RawAssign(*stack_.template Pop(1)); parseError_ = 0; errorOffset_ = 0; } else { parseError_ = reader.GetParseError(); errorOffset_ = reader.GetErrorOffset(); ClearStack(); } return *this; } //! Parse JSON text from a mutable string. /*! \tparam parseFlags Combination of ParseFlag. \param str Mutable zero-terminated string to be parsed. \return The document itself for fluent API. */ template GenericDocument& ParseInsitu(Ch* str) { GenericInsituStringStream s(str); return ParseStream(s); } //! Parse JSON text from a read-only string. /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). \param str Read-only zero-terminated string to be parsed. */ template GenericDocument& Parse(const Ch* str) { RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); GenericStringStream s(str); return ParseStream(s); } //! Whether a parse error was occured in the last parsing. bool HasParseError() const { return parseError_ != 0; } //! Get the message of parsing error. const char* GetParseError() const { return parseError_; } //! Get the offset in character of the parsing error. size_t GetErrorOffset() const { return errorOffset_; } //! Get the allocator of this document. Allocator& GetAllocator() { return stack_.GetAllocator(); } //! Get the capacity of stack in bytes. size_t GetStackCapacity() const { return stack_.GetCapacity(); } private: friend class GenericReader; // for Reader to call the following private handler functions // Implementation of Handler void Null() { new (stack_.template Push()) ValueType(); } void Bool(bool b) { new (stack_.template Push()) ValueType(b); } void Int(int i) { new (stack_.template Push()) ValueType(i); } void Uint(unsigned i) { new (stack_.template Push()) ValueType(i); } void Int64(int64_t i) { new (stack_.template Push()) ValueType(i); } void Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); } void Double(double d) { new (stack_.template Push()) ValueType(d); } void String(const Ch* str, SizeType length, bool copy) { if (copy) new (stack_.template Push()) ValueType(str, length, GetAllocator()); else new (stack_.template Push()) ValueType(str, length); } void StartObject() { new (stack_.template Push()) ValueType(kObjectType); } void EndObject(SizeType memberCount) { typename ValueType::Member* members = stack_.template Pop(memberCount); stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); } void StartArray() { new (stack_.template Push()) ValueType(kArrayType); } void EndArray(SizeType elementCount) { ValueType* elements = stack_.template Pop(elementCount); stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); } void ClearStack() { if (Allocator::kNeedFree) while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) (stack_.template Pop(1))->~ValueType(); else stack_.Clear(); } static const size_t kDefaultStackCapacity = 1024; internal::Stack stack_; const char* parseError_; size_t errorOffset_; }; typedef GenericDocument > Document; } // namespace rapidjson #endif // RAPIDJSON_DOCUMENT_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/filestream.h000066400000000000000000000017111256751517300270070ustar00rootroot00000000000000#ifndef RAPIDJSON_FILESTREAM_H_ #define RAPIDJSON_FILESTREAM_H_ #include namespace rapidjson { //! Wrapper of C file stream for input or output. /*! This simple wrapper does not check the validity of the stream. \implements Stream */ class FileStream { public: typedef char Ch; //!< Character type. Only support char. FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } char Peek() const { return current_; } char Take() { char c = current_; Read(); return c; } size_t Tell() const { return count_; } void Put(char c) { fputc(c, fp_); } // Not implemented char* PutBegin() { return 0; } size_t PutEnd(char*) { return 0; } private: void Read() { RAPIDJSON_ASSERT(fp_ != 0); int c = fgetc(fp_); if (c != EOF) { current_ = (char)c; count_++; } else current_ = '\0'; } FILE* fp_; char current_; size_t count_; }; } // namespace rapidjson #endif // RAPIDJSON_FILESTREAM_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/internal/000077500000000000000000000000001256751517300263175ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/internal/pow10.h000066400000000000000000000116151256751517300274420ustar00rootroot00000000000000#ifndef RAPIDJSON_POW10_ #define RAPIDJSON_POW10_ namespace rapidjson { namespace internal { //! Computes integer powers of 10 in double (10.0^n). /*! This function uses lookup table for fast and accurate results. \param n positive/negative exponent. Must <= 308. \return 10.0^n */ inline double Pow10(int n) { static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300, 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280, 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260, 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240, 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220, 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200, 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180, 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160, 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140, 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120, 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100, 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 }; RAPIDJSON_ASSERT(n <= 308); return n < -308 ? 0.0 : e[n + 308]; } } // namespace internal } // namespace rapidjson #endif // RAPIDJSON_POW10_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/internal/stack.h000066400000000000000000000045131256751517300276000ustar00rootroot00000000000000#ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ namespace rapidjson { namespace internal { /////////////////////////////////////////////////////////////////////////////// // Stack //! A type-unsafe stack for storing different types of data. /*! \tparam Allocator Allocator for allocating stack memory. */ template class Stack { public: Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { RAPIDJSON_ASSERT(stack_capacity_ > 0); if (!allocator_) own_allocator_ = allocator_ = new Allocator(); stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); stack_end_ = stack_ + stack_capacity_; } ~Stack() { Allocator::Free(stack_); delete own_allocator_; // Only delete if it is owned by the stack } void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } template T* Push(size_t count = 1) { // Expand the stack if needed if (stack_top_ + sizeof(T) * count >= stack_end_) { size_t new_capacity = stack_capacity_ * 2; size_t size = GetSize(); size_t new_size = GetSize() + sizeof(T) * count; if (new_capacity < new_size) new_capacity = new_size; stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); stack_capacity_ = new_capacity; stack_top_ = stack_ + size; stack_end_ = stack_ + stack_capacity_; } T* ret = (T*)stack_top_; stack_top_ += sizeof(T) * count; return ret; } template T* Pop(size_t count) { RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); stack_top_ -= count * sizeof(T); return (T*)stack_top_; } template T* Top() { RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); return (T*)(stack_top_ - sizeof(T)); } template T* Bottom() { return (T*)stack_; } Allocator& GetAllocator() { return *allocator_; } size_t GetSize() const { /*return stack_top_;*/ return stack_top_ - stack_; } size_t GetCapacity() const { return stack_capacity_; } private: Allocator* allocator_; Allocator* own_allocator_; char *stack_; char *stack_top_; char *stack_end_; size_t stack_capacity_; }; } // namespace internal } // namespace rapidjson #endif // RAPIDJSON_STACK_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/internal/strfunc.h000066400000000000000000000012501256751517300301520ustar00rootroot00000000000000#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ #define RAPIDJSON_INTERNAL_STRFUNC_H_ namespace rapidjson { namespace internal { //! Custom strlen() which works on different character types. /*! \tparam Ch Character type (e.g. char, wchar_t, short) \param s Null-terminated input string. \return Number of characters in the string. \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. */ template inline SizeType StrLen(const Ch* s) { const Ch* p = s; while (*p != '\0') ++p; return SizeType(p - s); } } // namespace internal } // namespace rapidjson #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/prettywriter.h000066400000000000000000000121671256751517300274470ustar00rootroot00000000000000#ifndef RAPIDJSON_PRETTYWRITER_H_ #define RAPIDJSON_PRETTYWRITER_H_ #include "writer.h" namespace rapidjson { //! Writer with indentation and spacing. /*! \tparam Stream Type of ouptut stream. \tparam Encoding Encoding of both source strings and output. \tparam Allocator Type of allocator for allocating memory of stack. */ template, typename Allocator = MemoryPoolAllocator<> > class PrettyWriter : public Writer { public: typedef Writer Base; typedef typename Base::Ch Ch; //! Constructor /*! \param stream Output stream. \param allocator User supplied allocator. If it is null, it will create a private one. \param levelDepth Initial capacity of */ PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} //! Set custom indentation. /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r'). \param indentCharCount Number of indent characters for each indentation level. \note The default indentation is 4 spaces. */ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); indentChar_ = indentChar; indentCharCount_ = indentCharCount; return *this; } //@name Implementation of Handler. //@{ PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { PrettyPrefix(kStringType); Base::WriteString(str, length); return *this; } PrettyWriter& StartObject() { PrettyPrefix(kObjectType); new (Base::level_stack_.template Push()) typename Base::Level(false); Base::WriteStartObject(); return *this; } PrettyWriter& EndObject(SizeType memberCount = 0) { RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; if (!empty) { Base::stream_.Put('\n'); WriteIndent(); } Base::WriteEndObject(); return *this; } PrettyWriter& StartArray() { PrettyPrefix(kArrayType); new (Base::level_stack_.template Push()) typename Base::Level(true); Base::WriteStartArray(); return *this; } PrettyWriter& EndArray(SizeType memberCount = 0) { RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; if (!empty) { Base::stream_.Put('\n'); WriteIndent(); } Base::WriteEndArray(); return *this; } //@} //! Simpler but slower overload. PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } protected: void PrettyPrefix(Type type) { if (Base::level_stack_.GetSize() != 0) { // this value is not at root typename Base::Level* level = Base::level_stack_.template Top(); if (level->inArray) { if (level->valueCount > 0) { Base::stream_.Put(','); // add comma if it is not the first element in array Base::stream_.Put('\n'); } else Base::stream_.Put('\n'); WriteIndent(); } else { // in object if (level->valueCount > 0) { if (level->valueCount % 2 == 0) { Base::stream_.Put(','); Base::stream_.Put('\n'); } else { Base::stream_.Put(':'); Base::stream_.Put(' '); } } else Base::stream_.Put('\n'); if (level->valueCount % 2 == 0) WriteIndent(); } if (!level->inArray && level->valueCount % 2 == 0) RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name level->valueCount++; } else RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); } void WriteIndent() { size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; PutN(Base::stream_, indentChar_, count); } Ch indentChar_; unsigned indentCharCount_; }; } // namespace rapidjson #endif // RAPIDJSON_RAPIDJSON_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/rapidjson.h000066400000000000000000000402011256751517300266420ustar00rootroot00000000000000#ifndef RAPIDJSON_RAPIDJSON_H_ #define RAPIDJSON_RAPIDJSON_H_ // Copyright (c) 2011 Milo Yip (miloyip@gmail.com) // Version 0.1 #include // malloc(), realloc(), free() #include // memcpy() /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_INT64DEFINE // Here defines int64_t and uint64_t types in global namespace. // If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. #ifndef RAPIDJSON_NO_INT64DEFINE #ifdef _MSC_VER typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else #include #endif #endif // RAPIDJSON_NO_INT64TYPEDEF /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_ENDIAN #define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine #define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine //! Endianness of the machine. /*! GCC provided macro for detecting endianness of the target machine. But other compilers may not have this. User can define RAPIDJSON_ENDIAN to either RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. */ #ifndef RAPIDJSON_ENDIAN #ifdef __BYTE_ORDER__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN #else #define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN #endif // __BYTE_ORDER__ #else #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise. #endif #endif // RAPIDJSON_ENDIAN /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD // Enable SSE2 optimization. //#define RAPIDJSON_SSE2 // Enable SSE4.2 optimization. //#define RAPIDJSON_SSE42 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) #define RAPIDJSON_SIMD #endif /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_SIZETYPEDEFINE #ifndef RAPIDJSON_NO_SIZETYPEDEFINE namespace rapidjson { //! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t. /*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE. */ typedef unsigned SizeType; } // namespace rapidjson #endif /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_ASSERT //! Assertion. /*! By default, rapidjson uses C assert() for assertion. User can override it by defining RAPIDJSON_ASSERT(x) macro. */ #ifndef RAPIDJSON_ASSERT #include #define RAPIDJSON_ASSERT(x) assert(x) #endif // RAPIDJSON_ASSERT namespace rapidjson { /////////////////////////////////////////////////////////////////////////////// // Allocator /*! \class rapidjson::Allocator \brief Concept for allocating, resizing and freeing memory block. Note that Malloc() and Realloc() are non-static but Free() is static. So if an allocator need to support Free(), it needs to put its pointer in the header of memory block. \code concept Allocator { static const bool kNeedFree; //!< Whether this allocator needs to call Free(). // Allocate a memory block. // \param size of the memory block in bytes. // \returns pointer to the memory block. void* Malloc(size_t size); // Resize a memory block. // \param originalPtr The pointer to current memory block. Null pointer is permitted. // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) // \param newSize the new size in bytes. void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); // Free a memory block. // \param pointer to the memory block. Null pointer is permitted. static void Free(void *ptr); }; \endcode */ /////////////////////////////////////////////////////////////////////////////// // CrtAllocator //! C-runtime library allocator. /*! This class is just wrapper for standard C library memory routines. \implements Allocator */ class CrtAllocator { public: static const bool kNeedFree = true; void* Malloc(size_t size) { return malloc(size); } void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { return realloc(originalPtr, newSize); } static void Free(void *ptr) { free(ptr); } }; /////////////////////////////////////////////////////////////////////////////// // MemoryPoolAllocator //! Default memory allocator used by the parser and DOM. /*! This allocator allocate memory blocks from pre-allocated memory chunks. It does not free memory blocks. And Realloc() only allocate new memory. The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. User may also supply a buffer as the first chunk. If the user-buffer is full then additional chunks are allocated by BaseAllocator. The user-buffer is not deallocated by this allocator. \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. \implements Allocator */ template class MemoryPoolAllocator { public: static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) //! Constructor with chunkSize. /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. \param baseAllocator The allocator for allocating memory chunks. */ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) { if (!baseAllocator_) ownBaseAllocator_ = baseAllocator_ = new BaseAllocator(); AddChunk(chunk_capacity_); } //! Constructor with user-supplied buffer. /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. The user buffer will not be deallocated when this allocator is destructed. \param buffer User supplied buffer. \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. \param baseAllocator The allocator for allocating memory chunks. */ MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) { RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); chunkHead_ = (ChunkHeader*)buffer; chunkHead_->capacity = size - sizeof(ChunkHeader); chunkHead_->size = 0; chunkHead_->next = 0; } //! Destructor. /*! This deallocates all memory chunks, excluding the user-supplied buffer. */ ~MemoryPoolAllocator() { Clear(); delete ownBaseAllocator_; } //! Deallocates all memory chunks, excluding the user-supplied buffer. void Clear() { while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) { ChunkHeader* next = chunkHead_->next; baseAllocator_->Free(chunkHead_); chunkHead_ = next; } } //! Computes the total capacity of allocated memory chunks. /*! \return total capacity in bytes. */ size_t Capacity() { size_t capacity = 0; for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) capacity += c->capacity; return capacity; } //! Computes the memory blocks allocated. /*! \return total used bytes. */ size_t Size() { size_t size = 0; for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) size += c->size; return size; } //! Allocates a memory block. (concept Allocator) void* Malloc(size_t size) { if (chunkHead_->size + size > chunkHead_->capacity) AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size; chunkHead_->size += size; return buffer; } //! Resizes a memory block (concept Allocator) void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { if (originalPtr == 0) return Malloc(newSize); // Do not shrink if new size is smaller than original if (originalSize >= newSize) return originalPtr; // Simply expand it if it is the last allocation and there is sufficient space if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { size_t increment = newSize - originalSize; if (chunkHead_->size + increment <= chunkHead_->capacity) { chunkHead_->size += increment; return originalPtr; } } // Realloc process: allocate and copy memory, do not free original buffer. void* newBuffer = Malloc(newSize); RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. return memcpy(newBuffer, originalPtr, originalSize); } //! Frees a memory block (concept Allocator) static void Free(void *ptr) {} // Do nothing private: //! Creates a new chunk. /*! \param capacity Capacity of the chunk in bytes. */ void AddChunk(size_t capacity) { ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity); chunk->capacity = capacity; chunk->size = 0; chunk->next = chunkHead_; chunkHead_ = chunk; } static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. //! Chunk header for perpending to each chunk. /*! Chunks are stored as a singly linked list. */ struct ChunkHeader { size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). size_t size; //!< Current size of allocated memory in bytes. ChunkHeader *next; //!< Next chunk in the linked list. }; ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. char *userBuffer_; //!< User supplied buffer. BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. }; /////////////////////////////////////////////////////////////////////////////// // Encoding /*! \class rapidjson::Encoding \brief Concept for encoding of Unicode characters. \code concept Encoding { typename Ch; //! Type of character. //! \brief Encode a Unicode codepoint to a buffer. //! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character. //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. //! \returns the pointer to the next character after the encoded data. static Ch* Encode(Ch *buffer, unsigned codepoint); }; \endcode */ /////////////////////////////////////////////////////////////////////////////// // UTF8 //! UTF-8 encoding. /*! http://en.wikipedia.org/wiki/UTF-8 \tparam CharType Type for storing 8-bit UTF-8 data. Default is char. \implements Encoding */ template struct UTF8 { typedef CharType Ch; static Ch* Encode(Ch *buffer, unsigned codepoint) { if (codepoint <= 0x7F) *buffer++ = codepoint & 0xFF; else if (codepoint <= 0x7FF) { *buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF); *buffer++ = 0x80 | ((codepoint & 0x3F)); } else if (codepoint <= 0xFFFF) { *buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF); *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); *buffer++ = 0x80 | (codepoint & 0x3F); } else { RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); *buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF); *buffer++ = 0x80 | ((codepoint >> 12) & 0x3F); *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); *buffer++ = 0x80 | (codepoint & 0x3F); } return buffer; } }; /////////////////////////////////////////////////////////////////////////////// // UTF16 //! UTF-16 encoding. /*! http://en.wikipedia.org/wiki/UTF-16 \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. \implements Encoding */ template struct UTF16 { typedef CharType Ch; static Ch* Encode(Ch* buffer, unsigned codepoint) { if (codepoint <= 0xFFFF) { RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair *buffer++ = codepoint; } else { RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); unsigned v = codepoint - 0x10000; *buffer++ = (v >> 10) + 0xD800; *buffer++ = (v & 0x3FF) + 0xDC00; } return buffer; } }; /////////////////////////////////////////////////////////////////////////////// // UTF32 //! UTF-32 encoding. /*! http://en.wikipedia.org/wiki/UTF-32 \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. \implements Encoding */ template struct UTF32 { typedef CharType Ch; static Ch *Encode(Ch* buffer, unsigned codepoint) { RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); *buffer++ = codepoint; return buffer; } }; /////////////////////////////////////////////////////////////////////////////// // Stream /*! \class rapidjson::Stream \brief Concept for reading and writing characters. For read-only stream, no need to implement PutBegin(), Put() and PutEnd(). For write-only stream, only need to implement Put(). \code concept Stream { typename Ch; //!< Character type of the stream. //! Read the current character from stream without moving the read cursor. Ch Peek() const; //! Read the current character from stream and moving the read cursor to next character. Ch Take(); //! Get the current read cursor. //! \return Number of characters read from start. size_t Tell(); //! Begin writing operation at the current read pointer. //! \return The begin writer pointer. Ch* PutBegin(); //! Write a character. void Put(Ch c); //! End the writing operation. //! \param begin The begin write pointer returned by PutBegin(). //! \return Number of characters written. size_t PutEnd(Ch* begin); } \endcode */ //! Put N copies of a character to a stream. template inline void PutN(Stream& stream, Ch c, size_t n) { for (size_t i = 0; i < n; i++) stream.Put(c); } /////////////////////////////////////////////////////////////////////////////// // StringStream //! Read-only string stream. /*! \implements Stream */ template struct GenericStringStream { typedef typename Encoding::Ch Ch; GenericStringStream(const Ch *src) : src_(src), head_(src) {} Ch Peek() const { return *src_; } Ch Take() { return *src_++; } size_t Tell() const { return src_ - head_; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } void Put(Ch c) { RAPIDJSON_ASSERT(false); } size_t PutEnd(Ch* begin) { RAPIDJSON_ASSERT(false); return 0; } const Ch* src_; //!< Current read position. const Ch* head_; //!< Original head of the string. }; typedef GenericStringStream > StringStream; /////////////////////////////////////////////////////////////////////////////// // InsituStringStream //! A read-write string stream. /*! This string stream is particularly designed for in-situ parsing. \implements Stream */ template struct GenericInsituStringStream { typedef typename Encoding::Ch Ch; GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} // Read Ch Peek() { return *src_; } Ch Take() { return *src_++; } size_t Tell() { return src_ - head_; } // Write Ch* PutBegin() { return dst_ = src_; } void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } size_t PutEnd(Ch* begin) { return dst_ - begin; } Ch* src_; Ch* dst_; Ch* head_; }; typedef GenericInsituStringStream > InsituStringStream; /////////////////////////////////////////////////////////////////////////////// // Type //! Type of JSON value enum Type { kNullType = 0, //!< null kFalseType = 1, //!< false kTrueType = 2, //!< true kObjectType = 3, //!< object kArrayType = 4, //!< array kStringType = 5, //!< string kNumberType = 6, //!< number }; } // namespace rapidjson #endif // RAPIDJSON_RAPIDJSON_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/reader.h000066400000000000000000000473741256751517300261350ustar00rootroot00000000000000#ifndef RAPIDJSON_READER_H_ #define RAPIDJSON_READER_H_ // Copyright (c) 2011 Milo Yip (miloyip@gmail.com) // Version 0.1 #include "rapidjson.h" #include "internal/pow10.h" #include "internal/stack.h" #include #ifdef RAPIDJSON_SSE42 #include #elif defined(RAPIDJSON_SSE2) #include #endif #ifndef RAPIDJSON_PARSE_ERROR #define RAPIDJSON_PARSE_ERROR(msg, offset) do { parseError_ = msg; errorOffset_ = offset; longjmp(jmpbuf_, 1); } while(false) #endif namespace rapidjson { /////////////////////////////////////////////////////////////////////////////// // ParseFlag //! Combination of parseFlags enum ParseFlag { kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. kParseInsituFlag = 1 //!< In-situ(destructive) parsing. }; /////////////////////////////////////////////////////////////////////////////// // Handler /*! \class rapidjson::Handler \brief Concept for receiving events from GenericReader upon parsing. \code concept Handler { typename Ch; void Null(); void Bool(bool b); void Int(int i); void Uint(unsigned i); void Int64(int64_t i); void Uint64(uint64_t i); void Double(double d); void String(const Ch* str, SizeType length, bool copy); void StartObject(); void EndObject(SizeType memberCount); void StartArray(); void EndArray(SizeType elementCount); }; \endcode */ /////////////////////////////////////////////////////////////////////////////// // BaseReaderHandler //! Default implementation of Handler. /*! This can be used as base class of any reader handler. \implements Handler */ template > struct BaseReaderHandler { typedef typename Encoding::Ch Ch; void Default() {} void Null() { Default(); } void Bool(bool b) { Default(); } void Int(int i) { Default(); } void Uint(unsigned i) { Default(); } void Int64(int64_t i) { Default(); } void Uint64(uint64_t i) { Default(); } void Double(double d) { Default(); } void String(const Ch* str, SizeType length, bool copy) { Default(); } void StartObject() { Default(); } void EndObject(SizeType memberCount) { Default(); } void StartArray() { Default(); } void EndArray(SizeType elementCount) { Default(); } }; /////////////////////////////////////////////////////////////////////////////// // SkipWhitespace //! Skip the JSON white spaces in a stream. /*! \param stream A input stream for skipping white spaces. \note This function has SSE2/SSE4.2 specialization. */ template void SkipWhitespace(Stream& stream) { Stream s = stream; // Use a local copy for optimization while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') s.Take(); stream = s; } #ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { static const char whitespace[16] = " \n\r\t"; __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); for (;;) { __m128i s = _mm_loadu_si128((const __m128i *)p); unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); if (r == 0) // all 16 characters are whitespace p += 16; else { // some of characters may be non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsigned long offset; if (_BitScanForward(&offset, r)) return p + offset; #else if (r != 0) return p + __builtin_ffs(r) - 1; #endif } } } #elif defined(RAPIDJSON_SSE2) //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { static const char whitespaces[4][17] = { " ", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); for (;;) { __m128i s = _mm_loadu_si128((const __m128i *)p); __m128i x = _mm_cmpeq_epi8(s, w0); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); unsigned short r = ~_mm_movemask_epi8(x); if (r == 0) // all 16 characters are whitespace p += 16; else { // some of characters may be non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsigned long offset; if (_BitScanForward(&offset, r)) return p + offset; #else if (r != 0) return p + __builtin_ffs(r) - 1; #endif } } } #endif // RAPIDJSON_SSE2 #ifdef RAPIDJSON_SIMD //! Template function specialization for InsituStringStream template<> inline void SkipWhitespace(InsituStringStream& stream) { stream.src_ = const_cast(SkipWhitespace_SIMD(stream.src_)); } //! Template function specialization for StringStream template<> inline void SkipWhitespace(StringStream& stream) { stream.src_ = SkipWhitespace_SIMD(stream.src_); } #endif // RAPIDJSON_SIMD /////////////////////////////////////////////////////////////////////////////// // GenericReader //! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. /*! GenericReader parses JSON text from a stream, and send events synchronously to an object implementing Handler concept. It needs to allocate a stack for storing a single decoded string during non-destructive parsing. For in-situ parsing, the decoded string is directly written to the source text string, no temporary buffer is required. A GenericReader object can be reused for parsing multiple JSON text. \tparam Encoding Encoding of both the stream and the parse output. \tparam Allocator Allocator type for stack. */ template > class GenericReader { public: typedef typename Encoding::Ch Ch; //! Constructor. /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) */ GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} //! Parse JSON text. /*! \tparam parseFlags Combination of ParseFlag. \tparam Stream Type of input stream. \tparam Handler Type of handler which must implement Handler concept. \param stream Input stream to be parsed. \param handler The handler to receive events. \return Whether the parsing is successful. */ template bool Parse(Stream& stream, Handler& handler) { parseError_ = 0; errorOffset_ = 0; if (setjmp(jmpbuf_)) { stack_.Clear(); return false; } SkipWhitespace(stream); if (stream.Peek() == '\0') RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell()); else { switch (stream.Peek()) { case '{': ParseObject(stream, handler); break; case '[': ParseArray(stream, handler); break; default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell()); return false; } SkipWhitespace(stream); if (stream.Peek() != '\0') RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell()); } return true; } bool HasParseError() const { return parseError_ != 0; } const char* GetParseError() const { return parseError_; } size_t GetErrorOffset() const { return errorOffset_; } private: // Parse object: { string : value, ... } template void ParseObject(Stream& stream, Handler& handler) { RAPIDJSON_ASSERT(stream.Peek() == '{'); stream.Take(); // Skip '{' handler.StartObject(); SkipWhitespace(stream); if (stream.Peek() == '}') { stream.Take(); handler.EndObject(0); // empty object return; } for (SizeType memberCount = 0;;) { if (stream.Peek() != '"') { RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell()); break; } ParseString(stream, handler); SkipWhitespace(stream); if (stream.Take() != ':') { RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell()); break; } SkipWhitespace(stream); ParseValue(stream, handler); SkipWhitespace(stream); ++memberCount; switch(stream.Take()) { case ',': SkipWhitespace(stream); break; case '}': handler.EndObject(memberCount); return; default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell()); } } } // Parse array: [ value, ... ] template void ParseArray(Stream& stream, Handler& handler) { RAPIDJSON_ASSERT(stream.Peek() == '['); stream.Take(); // Skip '[' handler.StartArray(); SkipWhitespace(stream); if (stream.Peek() == ']') { stream.Take(); handler.EndArray(0); // empty array return; } for (SizeType elementCount = 0;;) { ParseValue(stream, handler); ++elementCount; SkipWhitespace(stream); switch (stream.Take()) { case ',': SkipWhitespace(stream); break; case ']': handler.EndArray(elementCount); return; default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell()); } } } template void ParseNull(Stream& stream, Handler& handler) { RAPIDJSON_ASSERT(stream.Peek() == 'n'); stream.Take(); if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l') handler.Null(); else RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); } template void ParseTrue(Stream& stream, Handler& handler) { RAPIDJSON_ASSERT(stream.Peek() == 't'); stream.Take(); if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e') handler.Bool(true); else RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell()); } template void ParseFalse(Stream& stream, Handler& handler) { RAPIDJSON_ASSERT(stream.Peek() == 'f'); stream.Take(); if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e') handler.Bool(false); else RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); } // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). template unsigned ParseHex4(Stream& stream) { Stream s = stream; // Use a local copy for optimization unsigned codepoint = 0; for (int i = 0; i < 4; i++) { Ch c = s.Take(); codepoint <<= 4; codepoint += c; if (c >= '0' && c <= '9') codepoint -= '0'; else if (c >= 'A' && c <= 'F') codepoint -= 'A' - 10; else if (c >= 'a' && c <= 'f') codepoint -= 'a' - 10; else { RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); return 0; } } stream = s; // Restore stream return codepoint; } // Parse string, handling the prefix and suffix double quotes and escaping. template void ParseString(Stream& stream, Handler& handler) { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 static const Ch escape[256] = { Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 }; #undef Z16 Stream s = stream; // Use a local copy for optimization RAPIDJSON_ASSERT(s.Peek() == '\"'); s.Take(); // Skip '\"' Ch *head; SizeType len; if (parseFlags & kParseInsituFlag) head = s.PutBegin(); else len = 0; #define RAPIDJSON_PUT(x) \ do { \ if (parseFlags & kParseInsituFlag) \ s.Put(x); \ else { \ *stack_.template Push() = x; \ ++len; \ } \ } while(false) for (;;) { Ch c = s.Take(); if (c == '\\') { // Escape Ch e = s.Take(); if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e]) RAPIDJSON_PUT(escape[(unsigned char)e]); else if (e == 'u') { // Unicode unsigned codepoint = ParseHex4(s); if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair if (s.Take() != '\\' || s.Take() != 'u') { RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2); return; } unsigned codepoint2 = ParseHex4(s); if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) { RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2); return; } codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; } Ch buffer[4]; SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]); if (parseFlags & kParseInsituFlag) for (SizeType i = 0; i < count; i++) s.Put(buffer[i]); else { memcpy(stack_.template Push(count), buffer, count * sizeof(Ch)); len += count; } } else { RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1); return; } } else if (c == '"') { // Closing double quote if (parseFlags & kParseInsituFlag) { size_t length = s.PutEnd(head); RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); RAPIDJSON_PUT('\0'); // null-terminate the string handler.String(head, SizeType(length), false); } else { RAPIDJSON_PUT('\0'); handler.String(stack_.template Pop(len), len - 1, true); } stream = s; // restore stream return; } else if (c == '\0') { RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1); return; } else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1); return; } else RAPIDJSON_PUT(c); // Normal character, just copy } #undef RAPIDJSON_PUT } template void ParseNumber(Stream& stream, Handler& handler) { Stream s = stream; // Local copy for optimization // Parse minus bool minus = false; if (s.Peek() == '-') { minus = true; s.Take(); } // Parse int: zero / ( digit1-9 *DIGIT ) unsigned i; bool try64bit = false; if (s.Peek() == '0') { i = 0; s.Take(); } else if (s.Peek() >= '1' && s.Peek() <= '9') { i = s.Take() - '0'; if (minus) while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 214748364) { // 2^31 = 2147483648 if (i != 214748364 || s.Peek() > '8') { try64bit = true; break; } } i = i * 10 + (s.Take() - '0'); } else while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 429496729) { // 2^32 - 1 = 4294967295 if (i != 429496729 || s.Peek() > '5') { try64bit = true; break; } } i = i * 10 + (s.Take() - '0'); } } else { RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell()); return; } // Parse 64bit int uint64_t i64; bool useDouble = false; if (try64bit) { i64 = i; if (minus) while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 if (i64 != 922337203685477580uLL || s.Peek() > '8') { useDouble = true; break; } i64 = i64 * 10 + (s.Take() - '0'); } else while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 if (i64 != 1844674407370955161uLL || s.Peek() > '5') { useDouble = true; break; } i64 = i64 * 10 + (s.Take() - '0'); } } // Force double for big integer double d; if (useDouble) { d = (double)i64; while (s.Peek() >= '0' && s.Peek() <= '9') { if (d >= 1E307) { RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); return; } d = d * 10 + (s.Take() - '0'); } } // Parse frac = decimal-point 1*DIGIT int expFrac = 0; if (s.Peek() == '.') { if (!useDouble) { d = try64bit ? (double)i64 : (double)i; useDouble = true; } s.Take(); if (s.Peek() >= '0' && s.Peek() <= '9') { d = d * 10 + (s.Take() - '0'); --expFrac; } else { RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell()); return; } while (s.Peek() >= '0' && s.Peek() <= '9') { if (expFrac > -16) { d = d * 10 + (s.Peek() - '0'); --expFrac; } s.Take(); } } // Parse exp = e [ minus / plus ] 1*DIGIT int exp = 0; if (s.Peek() == 'e' || s.Peek() == 'E') { if (!useDouble) { d = try64bit ? (double)i64 : (double)i; useDouble = true; } s.Take(); bool expMinus = false; if (s.Peek() == '+') s.Take(); else if (s.Peek() == '-') { s.Take(); expMinus = true; } if (s.Peek() >= '0' && s.Peek() <= '9') { exp = s.Take() - '0'; while (s.Peek() >= '0' && s.Peek() <= '9') { exp = exp * 10 + (s.Take() - '0'); if (exp > 308) { RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); return; } } } else { RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); return; } if (expMinus) exp = -exp; } // Finish parsing, call event according to the type of number. if (useDouble) { d *= internal::Pow10(exp + expFrac); handler.Double(minus ? -d : d); } else { if (try64bit) { if (minus) handler.Int64(-(int64_t)i64); else handler.Uint64(i64); } else { if (minus) handler.Int(-(int)i); else handler.Uint(i); } } stream = s; // restore stream } // Parse any JSON value template void ParseValue(Stream& stream, Handler& handler) { switch (stream.Peek()) { case 'n': ParseNull (stream, handler); break; case 't': ParseTrue (stream, handler); break; case 'f': ParseFalse (stream, handler); break; case '"': ParseString(stream, handler); break; case '{': ParseObject(stream, handler); break; case '[': ParseArray (stream, handler); break; default : ParseNumber(stream, handler); } } static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. const char* parseError_; size_t errorOffset_; }; // class GenericReader //! Reader with UTF8 encoding and default allocator. typedef GenericReader > Reader; } // namespace rapidjson #endif // RAPIDJSON_READER_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/stringbuffer.h000066400000000000000000000025341256751517300273600ustar00rootroot00000000000000#ifndef RAPIDJSON_STRINGBUFFER_H_ #define RAPIDJSON_STRINGBUFFER_H_ #include "rapidjson.h" #include "internal/stack.h" namespace rapidjson { //! Represents an in-memory output stream. /*! \tparam Encoding Encoding of the stream. \tparam Allocator type for allocating memory buffer. \implements Stream */ template struct GenericStringBuffer { typedef typename Encoding::Ch Ch; GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} void Put(Ch c) { *stack_.template Push() = c; } void Clear() { stack_.Clear(); } const char* GetString() const { // Push and pop a null terminator. This is safe. *stack_.template Push() = '\0'; stack_.template Pop(1); return stack_.template Bottom(); } size_t Size() const { return stack_.Size(); } static const size_t kDefaultCapacity = 256; mutable internal::Stack stack_; }; typedef GenericStringBuffer > StringBuffer; //! Implement specialized version of PutN() with memset() for better performance. template<> inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { memset(stream.stack_.Push(n), c, n * sizeof(c)); } } // namespace rapidjson #endif // RAPIDJSON_STRINGBUFFER_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/rapidjson/writer.h000066400000000000000000000150061256751517300261720ustar00rootroot00000000000000#ifndef RAPIDJSON_WRITER_H_ #define RAPIDJSON_WRITER_H_ #include "rapidjson.h" #include "internal/stack.h" #include "internal/strfunc.h" #include // snprintf() or _sprintf_s() #include // placement new namespace rapidjson { //! JSON writer /*! Writer implements the concept Handler. It generates JSON text by events to an output stream. User may programmatically calls the functions of a writer to generate JSON text. On the other side, a writer can also be passed to objects that generates events, for example Reader::Parse() and Document::Accept(). \tparam Stream Type of ouptut stream. \tparam Encoding Encoding of both source strings and output. \implements Handler */ template, typename Allocator = MemoryPoolAllocator<> > class Writer { public: typedef typename Encoding::Ch Ch; Writer(Stream& stream, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level)) {} //@name Implementation of Handler //@{ Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } Writer& String(const Ch* str, SizeType length, bool copy = false) { Prefix(kStringType); WriteString(str, length); return *this; } Writer& StartObject() { Prefix(kObjectType); new (level_stack_.template Push()) Level(false); WriteStartObject(); return *this; } Writer& EndObject(SizeType memberCount = 0) { RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); level_stack_.template Pop(1); WriteEndObject(); return *this; } Writer& StartArray() { Prefix(kArrayType); new (level_stack_.template Push()) Level(true); WriteStartArray(); return *this; } Writer& EndArray(SizeType elementCount = 0) { RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); level_stack_.template Pop(1); WriteEndArray(); return *this; } //@} //! Simpler but slower overload. Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } protected: //! Information for each nested level struct Level { Level(bool inArray) : inArray(inArray), valueCount(0) {} bool inArray; //!< true if in array, otherwise in object size_t valueCount; //!< number of values in this level }; static const size_t kDefaultLevelDepth = 32; void WriteNull() { stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l'); } void WriteBool(bool b) { if (b) { stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e'); } else { stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e'); } } void WriteInt(int i) { if (i < 0) { stream_.Put('-'); i = -i; } WriteUint((unsigned)i); } void WriteUint(unsigned u) { char buffer[10]; char *p = buffer; do { *p++ = (u % 10) + '0'; u /= 10; } while (u > 0); do { --p; stream_.Put(*p); } while (p != buffer); } void WriteInt64(int64_t i64) { if (i64 < 0) { stream_.Put('-'); i64 = -i64; } WriteUint64((uint64_t)i64); } void WriteUint64(uint64_t u64) { char buffer[20]; char *p = buffer; do { *p++ = char(u64 % 10) + '0'; u64 /= 10; } while (u64 > 0); do { --p; stream_.Put(*p); } while (p != buffer); } //! \todo Optimization with custom double-to-string converter. void WriteDouble(double d) { char buffer[100]; #if _MSC_VER int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); #else int ret = snprintf(buffer, sizeof(buffer), "%g", d); #endif RAPIDJSON_ASSERT(ret >= 1); for (int i = 0; i < ret; i++) stream_.Put(buffer[i]); } void WriteString(const Ch* str, SizeType length) { static const char hexDigits[] = "0123456789ABCDEF"; static const char escape[256] = { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //0 1 2 3 4 5 6 7 8 9 A B C D E F 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 Z16, Z16, // 30~4F 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF #undef Z16 }; stream_.Put('\"'); for (const Ch* p = str; p != str + length; ++p) { if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) { stream_.Put('\\'); stream_.Put(escape[(unsigned char)*p]); if (escape[(unsigned char)*p] == 'u') { stream_.Put('0'); stream_.Put('0'); stream_.Put(hexDigits[(*p) >> 4]); stream_.Put(hexDigits[(*p) & 0xF]); } } else stream_.Put(*p); } stream_.Put('\"'); } void WriteStartObject() { stream_.Put('{'); } void WriteEndObject() { stream_.Put('}'); } void WriteStartArray() { stream_.Put('['); } void WriteEndArray() { stream_.Put(']'); } void Prefix(Type type) { if (level_stack_.GetSize() != 0) { // this value is not at root Level* level = level_stack_.template Top(); if (level->valueCount > 0) { if (level->inArray) stream_.Put(','); // add comma if it is not the first element in array else // in object stream_.Put((level->valueCount % 2 == 0) ? ',' : ':'); } if (!level->inArray && level->valueCount % 2 == 0) RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name level->valueCount++; } else RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); } Stream& stream_; internal::Stack level_stack_; }; } // namespace rapidjson #endif // RAPIDJSON_RAPIDJSON_H_ cpp-netlib-0.11.2-final/libs/network/example/twitter/search.cpp000066400000000000000000000030111256751517300244560ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011, 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include "rapidjson/rapidjson.h" #include "rapidjson/document.h" #include // This example uses the Twitter Search API. // // https://dev.twitter.com/docs/using-search int main(int argc, char *argv[]) { using namespace boost::network; using namespace rapidjson; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } try { http::client client; uri::uri base_uri("http://search.twitter.com/search.json"); std::cout << "Searching Twitter for query: " << argv[1] << std::endl; uri::uri search; search << base_uri << uri::query("q", uri::encoded(argv[1])); http::client::request request(search); http::client::response response = client.get(request); Document d; if (!d.Parse<0>(response.body().c_str()).HasParseError()) { const Value &results = d["results"]; for (SizeType i = 0; i < results.Size(); ++i) { const Value &user = results[i]["from_user_name"]; const Value &text = results[i]["text"]; std::cout << "From: " << user.GetString() << std::endl << " " << text.GetString() << std::endl << std::endl; } } } catch (std::exception &e) { std::cerr << e.what() << std::endl; } return 0; } cpp-netlib-0.11.2-final/libs/network/example/uri_builder.cpp000066400000000000000000000010331256751517300240160ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include using namespace boost::network; int main(int argc, char *argv[]) { uri::uri url; url << uri::scheme("http") << uri::host("www.github.com") << uri::path("/cpp-netlib"); std::cout << url << std::endl; return 0; } cpp-netlib-0.11.2-final/libs/network/experiment/000077500000000000000000000000001256751517300215355ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/experiment/CMakeLists.txt000066400000000000000000000015651256751517300243040ustar00rootroot00000000000000# Copyright 2013 Google, Inc. # Copyright 2010 Dean Michael Berris # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # Commenting this out until it's ready for prime-time later on. # include_directories(${CPP-NETLIB_SOURCE_DIR}) # set(CMAKE_BUILD_TYPE Release) # if (Boost_FOUND) # add_executable(cpp-netlib-utils_base64_experiment utils_base64_experiment.cpp) # target_link_libraries(cpp-netlib-utils_base64_experiment ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) # if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # target_link_libraries(cpp-netlib-utils_base64_experiment rt) # endif() # set_target_properties(cpp-netlib-utils_base64_experiment # PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) # endif() cpp-netlib-0.11.2-final/libs/network/experiment/utils/000077500000000000000000000000001256751517300226755ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/experiment/utils/base64-standalone.hpp000066400000000000000000000422561256751517300266310ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_STANDALONE_HPP #define BOOST_NETWORK_UTILS_BASE64_STANDALONE_HPP #include #include #include #include #include namespace boost { namespace network { namespace utils { // Implements a BASE64 converter working on an iterator range from the // scratch. If the input sequence does not end at the three-byte // boundary, // the last encoded value part is remembered in an encoding state to be // able // to continue with the next chunk; the BASE64 encoding processes the // input // by byte-triplets. // // Summarized interface: // // struct state { // bool empty () const; // void clear(); // } // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output, State & rest) // OutputIterator encode_rest(OutputIterator output, State & rest) // OutputIterator encode(InputRange const & input, OutputIterator output, // State & rest) // OutputIterator encode(char const * value, OutputIterator output, // state & rest) // std::basic_string encode(InputRange const & value, State & rest) // std::basic_string encode(char const * value, state & rest) // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) { namespace base64_standalone { namespace detail { // Picks a character from the output alphabet for another 6-bit value // from the input sequence to encode. template char encode_value(Value value) { static char const* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" "+/"; return encoding[static_cast(value)]; } } // namespace detail // Stores the state after processing the last chunk by the encoder. If // the // chunk byte-length is not divisible by three, the last (incomplete) // value // quantum canot be encoded right away; it has to wait for the next // chunk // of octets which will be processed joined (as if the trailing rest // from // the previous one was at its beinning). template struct state { state() : triplet_index(0), last_encoded_value(0) {} state(state const& source) : triplet_index(source.triplet_index), last_encoded_value(source.last_encoded_value) {} bool empty() const { return triplet_index == 0; } void clear() { // indicate that no rest has been left in the last encoded value // and no padding is needed for the encoded output triplet_index = 0; // the last encoded value, which may have been left from the last // encoding step, must be zeroed too; it is important before the // next encoding begins, because it works as a cyclic buffer and // must start empty - with zero last_encoded_value = 0; } unsigned short padding_length() const { // the fewer octets from the triplet processed, the more characters // needed as padding padding - that is why the complement here return triplet_index ? 3 - triplet_index : 0; } protected: // number of the octet in the incomplete quantum, which has been // processed the last time; 0 means that the previous quantum was // complete 3 octets, 1 that just one octet was avalable and 2 that // two octets were available unsigned char triplet_index; // the value made of the previously shifted and or-ed octets which // was not completely split to 6-bit codes, because the last quantum // did not stop on the boundary of three octets Value last_encoded_value; // encoding of an input chunk needs to read and update the state template friend OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest); // finishing the encoding needs to read and clear the state template friend OutputIterator encode_rest(OutputIterator output, State& rest); }; // Encodes an input sequence to BASE64 writing it to the output iterator // and stopping if the last input tree-octet quantum was not complete, // in // which case it stores the state for the later continuation, when // another // input chunk is ready for the encoding. The encoding must be finished // by calling the encode_rest after processing the last chunk. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer.begin(), buffer.end(), appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest) { typedef typename iterator_value::type value_type; // continue with the rest of the last chunk - 2 or 4 bits which // are already shifted to the left and need to be or-ed with the // continuing data up to the target 6 bits value_type encoded_value = rest.last_encoded_value; // if the previous chunk stopped at encoding the first (1) or the // second // (2) octet of the three-byte quantum, jump to the right place, // otherwise start the loop with an empty encoded value buffer switch (rest.triplet_index) { // this loop processes the input sequence of bit-octets by bits, // shifting the current_value (used as a cyclic buffer) left and // or-ing next bits there, while pulling the bit-sextets from the // high word of the current_value for (value_type current_value;;) { case 0: // if the input sequence is empty or reached its end at the // 3-byte boundary, finish with an empty encoding state if (begin == end) { rest.triplet_index = 0; // the last encoded value is not interesting - it would not // be used, because processing of the next chunk will start // at the 3-byte boundary rest.last_encoded_value = 0; return output; } // read the first octet from the current triplet current_value = *begin++; // use just the upper 6 bits to encode it to the target alphabet encoded_value = (current_value & 0xfc) >> 2; *output++ = detail::encode_value(encoded_value); // shift the remaining two bits up to make place for the upoming // part of the next octet encoded_value = (current_value & 0x03) << 4; case 1: // if the input sequence reached its end after the first octet // from the quantum triplet, store the encoding state and finish if (begin == end) { rest.triplet_index = 1; rest.last_encoded_value = encoded_value; return output; } // read the second first octet from the current triplet current_value = *begin++; // combine the upper four bits (as the lower part) with the // previous two bits to encode it to the target alphabet encoded_value |= (current_value & 0xf0) >> 4; *output++ = detail::encode_value(encoded_value); // shift the remaining four bits up to make place for the // upoming // part of the next octet encoded_value = (current_value & 0x0f) << 2; case 2: // if the input sequence reached its end after the second octet // from the quantum triplet, store the encoding state and finish if (begin == end) { rest.triplet_index = 2; rest.last_encoded_value = encoded_value; return output; } // read the third octet from the current triplet current_value = *begin++; // combine the upper two bits (as the lower part) with the // previous four bits to encode it to the target alphabet encoded_value |= (current_value & 0xc0) >> 6; *output++ = detail::encode_value(encoded_value); // encode the remaining 6 bits to the target alphabet encoded_value = current_value & 0x3f; *output++ = detail::encode_value(encoded_value); } } return output; } // Finishes encoding of the previously processed chunks. If their total // byte-length was divisible by three, nothing is needed, if not, the // last // quantum will be encoded as if padded with zeroes, which will be // indicated // by appending '=' characters to the output. This method must be // always // used at the end of encoding, if the previous chunks were encoded by // the // method overload accepting the encoding state. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer.begin(), buffer.end(), appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode_rest(OutputIterator output, State& rest) { if (!rest.empty()) { // process the last part of the trailing octet (either 4 or 2 bits) // as if the input was padded with zeros - without or-ing the next // input value to it; it has been already shifted to the left *output++ = detail::encode_value(rest.last_encoded_value); // at least one padding '=' will be always needed - at least two // bits are missing in the finally encoded 6-bit value *output++ = '='; // if the last octet was the first in the triplet (the index was // 1), four bits are missing in the finally encoded 6-bit value; // another '=' character is needed for the another two bits if (rest.triplet_index < 2) *output++ = '='; // clear the state all the time to make sure that another call to // the encode_rest would not cause damage; the last encoded value, // which may have been left there, must be zeroed too; it is // important before the next encoding begins, because it works as // a cyclic buffer and must start empty - with zero rest.clear(); } return output; } // Encodes a part of an input sequence specified by the pair of begin // and // end iterators.to BASE64 writing it to the output iterator. If its // total // byte-length was not divisible by three, the output will be padded by // the // '=' characters. If you encode an input consisting of mutiple chunks, // use the method overload maintaining the encoding state. // // std::vector buffer = ...; // std::basic_string result; // base64::encode(buffer.begin(), buffer.end(), // std::back_inserter(result)); template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { state::type> rest; output = encode(begin, end, output, rest); return encode_rest(output, rest); } // Encodes an entire input sequence to BASE64, which either supports // begin() // and end() methods returning boundaries of the sequence or the // boundaries // can be computed by the Boost::Range, writing it to the output // iterator // and stopping if the last input tree-octet quantum was not complete, // in // which case it stores the state for the later continuation, when // another // input chunk is ready for the encoding. The encoding must be finished // by calling the encode_rest after processing the last chunk. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode(buffer, appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(InputRange const& input, OutputIterator output, State& rest) { return encode(boost::begin(input), boost::end(input), output, rest); } // Encodes an entire string literal to BASE64, writing it to the output // iterator and stopping if the last input tree-octet quantum was not // complete, in which case it stores the state for the later // continuation, // when another input chunk is ready for the encoding. The encoding // must // be finished by calling the encode_rest after processing the last // chunk. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result; // std::back_insert_iterator > appender(result); // base64::state rest; // base64::encode("ab", appender, rest); // ... // base64::encode_rest(appender, rest); template OutputIterator encode(char const* value, OutputIterator output, state& rest) { return encode(value, value + strlen(value), output, rest); } // Encodes an entire input sequence to BASE64 writing it to the output // iterator, which either supports begin() and end() methods returning // boundaries of the sequence or the boundaries can be computed by the // Boost::Range. If its total byte-length was not divisible by three, // the output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use the method overload // maintaining // the encoding state. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result; // base64::encode(buffer, std::back_inserter(result)); template OutputIterator encode(InputRange const& value, OutputIterator output) { return encode(boost::begin(value), boost::end(value), output); } // Encodes an entire string literal to BASE64 writing it to the output // iterator. If its total length (without the trailing zero) was not // divisible by three, the output will be padded by the '=' characters. // If you encode an input consisting of mutiple chunks, use the method // overload maintaining the encoding state. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result; // base64::encode("ab", std::back_inserter(result)); template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } // Encodes an entire input sequence to BASE64 returning the result as // string, which either supports begin() and end() methods returning // boundaries of the sequence or the boundaries can be computed by the // Boost::Range. If its total byte-length was not divisible by three, // the output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use other method maintaining // the encoding state writing to an output iterator. // // Warning: Buffers identified by C-pointers are processed including // their // termination character, if they have any. This is unexpected at least // for the storing literals, which have a specialization here to avoid // it. // // std::vector buffer = ...; // std::basic_string result = base64::encode(buffer); template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } // Encodes an entire string literal to BASE64 returning the result as // string. If its total byte-length was not divisible by three, the // output will be padded by the '=' characters. If you encode an // input consisting of mutiple chunks, use other method maintaining // the encoding state writing to an output iterator. // // The string literal is encoded without processing its terminating zero // character, which is the usual expectation. // // std::basic_string result = base64::encode("ab"); template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } // the function overloads for string literals encode the input without // the terminating zero, which is usually expected, because the trailing // zero byte is not considered a part of the string value; the overloads // foran input range would wrap the string literal by Boost.Range and // encodethe full memory occupated by the string literal - including the // unwanted last zero byte } // namespace base64_standalone } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_STANDALONE_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/base64-stateful_buffer.hpp000066400000000000000000000202301256751517300276450ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP #define BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP #include #include #include #include #include #include #include #include namespace boost { namespace network { namespace utils { // Uses base64_from_binary and transform_width to implement a BASE64 // converter working on an iterator range. Because the transform_width // encodes immediately every input byte, while the BASE64 encoding // processes // the input by byte-triplets, if the input sequence does not end at the // three-byte boundary, the rest is remembered in an encoding state to // be able to continue with the next chunk. It uses an internal buffer // of 4095 input octets to be able to read the input by octet-triplets. // // Summarized interface: // // struct state { // bool empty () const; // void clear(); // } // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output, State & rest) // OutputIterator encode_rest(OutputIterator output, State & rest) // OutputIterator encode(InputRange const & input, OutputIterator output, // State & rest) // OutputIterator encode(char const * value, OutputIterator output, // state & rest) // std::basic_string encode(InputRange const & value, State & rest) // std::basic_string encode(char const * value, state & rest) // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) { namespace base64_stateful_buffer { // force using the ostream_iterator from boost::archive to write wide // characters reliably, althoth wchar_t may not be a native character // type using namespace boost::archive::iterators; template struct state { state() : size(0) {} state(state const& source) : data(source.data), size(source.size) {} bool empty() const { return size == 0; } void clear() { size = 0; } private: typedef boost::array data_type; typedef typename data_type::const_iterator const_iterator_type; template void fill(InputIterator begin, InputIterator end) { // make sure that there is always zero padding for the incomplete // triplet; the encode will read three bytes from the vector data.fill(0); size = std::copy(begin, end, data.begin()) - data.begin(); } template OutputIterator write(OutputIterator output) { return std::copy(data.begin(), data.begin() + size, output); } const_iterator_type begin() const { return data.begin(); } const_iterator_type end() const { return data.begin() + size; } data_type data; std::size_t size; template friend OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest); template friend OutputIterator encode_rest(OutputIterator output, State& rest); }; template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest) { typedef typename iterator_value::type value_type; // declare the buffer type for 1365 octet triplets; make sure that the // number is divisible by three if you change it (!) const std::size_t BufferSize = 4095; BOOST_STATIC_ASSERT(BufferSize / 3 * 3 == BufferSize); typedef boost::array buffer_type; // declare the encoding iterator type typedef base64_from_binary > base64_text; if (begin != end) { // declare the buffer, a variable to remmeber its size and the size // which can be encoded (the nearest lower size divisible by three) buffer_type buffer; std::size_t buffer_size = 0, encode_size = 0; // if the previous state contained an incomplete octet triplet, put // it to the start of the buffer to get it prepended to the input if (!rest.empty()) { buffer_size = rest.size; rest.write(buffer.begin()); rest.clear(); } // iterate over the entire input while (begin != end) { // fill the buffer with the input as much as possible while (begin != end && buffer_size < buffer.size()) buffer[buffer_size++] = *begin++; // if the buffer could not be filled completely, compute // the size which can be encoded immediately. encode_size = buffer_size / 3 * 3; if (encode_size > 0) { // encode the buffer part of the size divisible by three base64_text base64_begin(buffer.begin()), base64_end(buffer.begin() + encode_size); output = std::copy(base64_begin, base64_end, output); // zero the buffer size to prepare for the next iteration buffer_size = 0; } } // if the complete buffer could not be encoded, store the last // incomplete octet triplet to the transiting state if (buffer_size > encode_size) rest.fill(buffer.begin() + encode_size, buffer.begin() + buffer_size); } return output; } template OutputIterator encode_rest(OutputIterator output, State& rest) { typedef typename State::const_iterator_type iterator_type; // declare the encoding iterator type typedef base64_from_binary > base64_text; if (!rest.empty()) { // encode the incomplete octet triplet using zeros as padding // (an artificial input continuation) base64_text base64_begin(rest.begin()), base64_end(rest.end()); output = std::copy(base64_begin, base64_end, output); // at least one padding '=' will be always needed - at least two // bits are missing in the finally encoded 6-bit value if (rest.size > 0) { *output++ = '='; // if the last octet was the first in the triplet (the index was, // four bits are missing in the finally encoded 6-bit value; // another '=' character is needed for the another two bits if (rest.size == 1) *output++ = '='; } rest.clear(); } return output; } template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { state::type> rest; output = encode(begin, end, output, rest); return encode_rest(output, rest); } template OutputIterator encode(InputRange const& value, OutputIterator output) { return encode(boost::begin(value), boost::end(value), output); } template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } // the function overloads for string literals encode the input without // the terminating zero, which is usually expected, because the trailing // zero byte is not considered a part of the string value; the overloads // foran input range would wrap the string literal by Boost.Range and // encodethe full memory occupated by the string literal - including the // unwanted last zero byte } // namespace base64_stateful_buffer } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/base64-stateful_iterator.hpp000066400000000000000000000144741256751517300302420ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_STATEFUL_ITERATOR_HPP #define BOOST_NETWORK_UTILS_BASE64_STATEFUL_ITERATOR_HPP #include #include "iterators/stateful_transform_width.hpp" #include "iterators/iterator_with_state.hpp" #include #include #include #include #include #include #include namespace boost { namespace network { namespace utils { // Uses base64_from_binary and stateful_transform_width to implement a // BASE64 // converter working on an iterator range. Based on transform_width, the // stateful_transform_width relies on the end iterator and the encoding // state // stored in the transformed iterator; usually by using the iterator // adaptor // - iterator_with_state. Storing the encoding state in the transformed // iterator practically means adapting every such iterator, but the // iterators // which wrap the stateful_transform_width, like the base64_from_binary, // do // not need to be re-declared with an extra constructor to pass the end // iterator and the encoding state to an extended transform_width. // // Summarized interface: // // struct state { // bool empty () const; // void clear(); // unsigned short padding_length() const; // } // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output, State & rest) // OutputIterator encode_rest(OutputIterator output, State & rest) // OutputIterator encode(InputRange const & input, OutputIterator output, // State & rest) // OutputIterator encode(char const * value, OutputIterator output, // state & rest) // std::basic_string encode(InputRange const & value, State & rest) // std::basic_string encode(char const * value, state & rest) // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) { namespace base64_stateful_iterator { // force using the ostream_iterator from boost::archive to write wide // characters reliably, althoth wchar_t may not be a native character // type using namespace boost::archive::iterators; using namespace boost::network::utils::iterators; template struct state : public state_for_transform_width { typedef state this_t; typedef state_for_transform_width super_t; state() {} state(this_t const& source) : super_t(source) {} unsigned short padding_length() const { // the BASE64 encoding unit consists of 6 bits; if the 8-bit // input cannot be completely divided to 6-bit chunks, 2 or // 4 bits can remain, which the bit_count returns as displacement // of the 8-bit value (right shift length) - 6 or 4 unsigned short bits = super_t::bit_count(); return bits > 0 ? 6 / bits : 0; } }; template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest) { typedef boost::iterator_with_state stateful_input; // declare the encoding iterator type typedef base64_from_binary > base64_input; // declare the stateful transforming itarators stateful_input stateful_begin(begin, end, rest), stateful_end(end); // declare the iterator to transform the encoded 6-bit units to the // BASE64 alphabet base64_input base64_begin(stateful_begin), base64_end(stateful_end); return std::copy(base64_begin, base64_end, output); } template OutputIterator encode_rest(OutputIterator output, State& rest) { unsigned short padding_length = rest.padding_length(); if (padding_length > 0) { typedef typename State::value_type value_type; // declare the input padding type and the adapted iterator including // the encoding state for it - see below typedef boost::array pillow_input; typedef boost::iterator_with_state stateful_input; // declare the encoding iterator type typedef base64_from_binary > base64_input; // although containing encoding state to continue with the next // chunk, the stateful_transform_width still reads from the input // iterator and needs the complete quantum for the encoding; the // zero padding will make for an artifitial input ending here pillow_input pillow = {{0, 0}}; stateful_input stateful_begin(pillow.begin(), pillow.end(), rest); base64_input base64_begin(stateful_begin); *output++ = *base64_begin; if (padding_length > 0) { *output++ = '='; if (padding_length > 1) *output++ = '='; } } return output; } template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { state::type> rest; output = encode(begin, end, output, rest); return encode_rest(output, rest); } template OutputIterator encode(InputRange const& input, OutputIterator output) { return encode(boost::begin(input), boost::end(input), output); } template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } } // namespace base64_stateful_iterator } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_STATEFUL_ITERATOR_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/base64-stateful_transform.hpp000066400000000000000000000147241256751517300304220ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_STATEFUL_TRANSFORM_HPP #define BOOST_NETWORK_UTILS_BASE64_STATEFUL_TRANSFORM_HPP #include "iterators/stateful_base64_from_binary.hpp" #include "iterators/transform_width_with_state.hpp" #include #include #include #include #include #include #include namespace boost { namespace network { namespace utils { // Uses stateful_base64_from_binary and transform_width_with_state to // implement a BASE64 converter working on an iterator range. Based on // transform_width, the transform_width_with_state stores the end iterator // and the encoding state to be able to process the encoding input by // chunks. The stateful_base64_from_binary just passes through the // constructor parameters, which the transform_width_with_state needs. // Storing the encoding state in the transforming iterator makes any // input iterator transformable without adapting, but the iterators which // wrap it, like the base64_from_binary, needs to be re-declared with // the extra constructor. // // Summarized interface: // // struct state { // bool empty () const; // void clear(); // unsigned short padding_length() const; // } // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output, State & rest) // OutputIterator encode_rest(OutputIterator output, State & rest) // OutputIterator encode(InputRange const & input, OutputIterator output, // State & rest) // OutputIterator encode(char const * value, OutputIterator output, // state & rest) // std::basic_string encode(InputRange const & value, State & rest) // std::basic_string encode(char const * value, state & rest) // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) { namespace base64_stateful_transform { // force using the ostream_iterator from boost::archive to write wide // characters reliably, althoth wchar_t may not be a native character // type using namespace boost::archive::iterators; using namespace boost::network::utils::iterators; template struct state : public transform_width_state { typedef transform_width_state super_t; state() {} state(state const& source) : super_t(source) {} unsigned short padding_length() const { // the BASE64 encoding unit consists of 6 bits; if the 8-bit // input cannot be completely divided to 6-bit chunks, 2 or // 4 bits can remain, which the bit_count returns as displacement // of the 8-bit value (right shift length) - 6 or 4 unsigned short bits = super_t::bit_count(); return bits > 0 ? 6 / bits : 0; } }; template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output, State& rest) { // declare the transforming iterator type typedef transform_width_with_state stateful_input; // declare the encoding iterator type typedef stateful_base64_from_binary base64_input; base64_input base64_begin(begin, end, rest), base64_end(end); return std::copy(base64_begin, base64_end, output); } template OutputIterator encode_rest(OutputIterator output, State& rest) { unsigned short padding_length = rest.padding_length(); if (padding_length > 0) { typedef typename State::value_type value_type; // declare the input padding type and the adapted iterator including // the encoding state for it - see below typedef boost::array pillow_input; // declare the transforming iterator type typedef transform_width_with_state stateful_input; // declare the encoding iterator type typedef stateful_base64_from_binary base64_input; // although containing encoding state to continue with the next // chunk, the stateful_transform_width still reads from the input // iterator and needs the complete quantum for the encoding; the // zero padding will make for an artifitial input ending here pillow_input pillow = {{0, 0}}; base64_input base64_begin(pillow.begin(), pillow.end(), rest), base64_end(pillow.end()); *output++ = *base64_begin; if (padding_length > 0) { *output++ = '='; if (padding_length > 1) *output++ = '='; } } return output; } template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { state::type> rest; output = encode(begin, end, output, rest); return encode_rest(output, rest); } template OutputIterator encode(InputRange const& input, OutputIterator output, State& rest) { return encode(boost::begin(input), boost::end(input), output, rest); } template OutputIterator encode(char const* value, OutputIterator output, state& rest) { return encode(value, value + strlen(value), output, rest); } template OutputIterator encode(InputRange const& input, OutputIterator output) { return encode(boost::begin(input), boost::end(input), output); } template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } } // namespace base64_stateful_transform } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_STATEFUL_TRANSFORM_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/base64-stateless.hpp000066400000000000000000000066041256751517300265050ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_BASE64_STATELESS_HPP #define BOOST_NETWORK_UTILS_BASE64_STATELESS_HPP #include #include #include #include #include #include #include namespace boost { namespace network { namespace utils { // Uses base64_from_binary and transform_width to implement a BASE64 // converter working on an iterator range. While it is a nice example // of code reuse, the input sequence must either end at the three-byte // boundary or be padded with a zero, otherwise the transforming // iterator tries to read behind the end iterator. // // Summarized interface: // // OutputIterator encode(InputIterator begin, InputIterator end, // OutputIterator output) // OutputIterator encode(InputRange const & input, OutputIterator output) // OutputIterator encode(char const * value, OutputIterator output) // std::basic_string encode(InputRange const & value) // std::basic_string encode(char const * value) namespace base64_stateless { // force using the ostream_iterator from boost::archive to write wide // characters reliably, although wchar_t may not be a native character // type using namespace boost::archive::iterators; template OutputIterator encode(InputIterator begin, InputIterator end, OutputIterator output) { // declare the encoding iterator type typedef base64_from_binary > base64_text; base64_text base64_begin(begin), base64_end(end); // iterate through the input by the encoding iterator one encoded // unit at a time to learn how many units were encoded without // requiring neither the input iterators nor the output ones to be // random access iterators (supporting subtraction end - begin) std::size_t encoded_count = 0; while (base64_begin != base64_end) { *output++ = *base64_begin++; ++encoded_count; } // the encoding iterator advanced so many times as is the encoded // output // size, but the padding is determined by the number of bytes in the // last // (incomplete) input byte-triplet; first compute the input length and // then how many trailing bytes followed the last complete quantum std::size_t incomplete_length = encoded_count * 6 / 8 % 3; if (incomplete_length > 0) { *output++ = '='; if (incomplete_length < 2) *output++ = '='; } return output; } template OutputIterator encode(InputRange const& input, OutputIterator output) { return encode(boost::begin(input), boost::end(input), output); } template OutputIterator encode(char const* value, OutputIterator output) { return encode(value, value + strlen(value), output); } template std::basic_string encode(InputRange const& value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } template std::basic_string encode(char const* value) { std::basic_string result; encode(value, std::back_inserter(result)); return result; } } // namespace base64_stateless } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_BASE64_STATELESS_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/iterators/000077500000000000000000000000001256751517300247115ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/experiment/utils/iterators/iterator_with_state.hpp000066400000000000000000000044061256751517300315120ustar00rootroot00000000000000#ifndef BOOST_ITERATOR_WITH_STATE_HPP #define BOOST_ITERATOR_WITH_STATE_HPP #include #include #include #include #include // The class iterator_with_state adds storing the end iterator and the // transforming state to an existing iterator, so that it can be used as // a base in the transform_width_with_state. namespace boost { template class iterator_with_state; namespace detail { template struct iterator_with_state_base { typedef iterator_adaptor< iterator_with_state, Iterator, use_default, typename mpl::if_< is_convertible::type, random_access_traversal_tag>, bidirectional_traversal_tag, use_default>::type> type; }; } template class iterator_with_state : public detail::iterator_with_state_base::type { typedef typename detail::iterator_with_state_base::type super_t; friend class iterator_core_access; public: iterator_with_state() {} typedef State state_type; iterator_with_state(Iterator x, Iterator end_, State& state_) : super_t(x), m_end(end_), m_state(&state_) {} iterator_with_state(Iterator x) : super_t(x) {} template iterator_with_state( iterator_with_state const& t, typename enable_if_convertible::type* = 0) : super_t(t.base()), m_end(t.end()), m_state(&t.state()) {} Iterator const& end() const { return m_end; } State const& state() const { return *m_state; } State& state() { return *m_state; } private: void increment() { ++this->base_reference(); } void decrement() { --(this->base_reference()); } Iterator m_end; State* m_state; }; template iterator_with_state make_iterator_with_state( Iterator x, Iterator end = Iterator(), State state = State()) { return iterator_with_state(x, end, state); } } // namespace boost #endif // BOOST_ITERATOR_WITH_STATE_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/iterators/stateful_base64_from_binary.hpp000066400000000000000000000044161256751517300330110ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_BASE64_FROM_BINARY_HPP #define BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_BASE64_FROM_BINARY_HPP #include #include #include #include #include // The class stateful_base64_from_binary works like base64_from_binary from // boost/archive/iterators, only expecting an iterator base which supports // transformng state and needs the end iterator and the state passed to the // constructor. The transform_width_with_state, for example. namespace boost { namespace network { namespace utils { namespace iterators { namespace detail { template struct from_6_bit { typedef CharType result_type; CharType operator()(CharType t) const { const char* lookup_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/"; BOOST_ASSERT(t < 64); return lookup_table[static_cast(t)]; } }; } // namespace detail template ::type> class stateful_base64_from_binary : public transform_iterator, Base> { friend class boost::iterator_core_access; typedef transform_iterator, Base> super_t; public: template stateful_base64_from_binary(BOOST_PFTO_WRAPPER(T) start, BOOST_PFTO_WRAPPER(T) end, State& state) : super_t( Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)), end, state), detail::from_6_bit()) {} template stateful_base64_from_binary(BOOST_PFTO_WRAPPER(T) start) : super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start))), detail::from_6_bit()) {} // intel 7.1 doesn't like default copy constructor stateful_base64_from_binary(const stateful_base64_from_binary& rhs) : super_t(Base(rhs.base_reference()), detail::from_6_bit()) {} }; } // namespace iterators } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_BASE64_FROM_BINARY_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/iterators/stateful_transform_width.hpp000066400000000000000000000156201256751517300325470ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_TRANSFORM_WIDTH_HPP #define BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_TRANSFORM_WIDTH_HPP #include #include #include #include // The class stateful_transform_width works like transform_width from // boost/archive/iterators if the collection of input values can be converted // to the output without padding the input with zeros. (The total input bit // count is divisible by the bit size of an output value.) It it cannot, the // partially encoded last value, which would have to be padded with zero, // is stored to the state_for_transform_width, which can be used later to // continue the encoding when another chunk of input values is available. // The end iterator is needed to detect the end transformation. // // The encoding state and the end iterator are owned by the input iterator // which has to provide access to them. The iterator adaptor // iterator_with_state is supposed to be used to add this functionality to // existing iterators. namespace boost { namespace network { namespace utils { namespace iterators { template class state_for_transform_width { public: typedef Value value_type; state_for_transform_width() : m_displacement(0) {} state_for_transform_width(state_for_transform_width const &source) : m_displacement(source.m_displacement), m_buffer(source.m_buffer) {} bool empty() const { return bit_count() == 0; } void clear() { m_displacement = 0; } protected: unsigned short bit_count() const { return m_displacement > 0 ? BitsIn - m_displacement : 0; } private: unsigned short m_displacement; value_type m_buffer; template friend class stateful_transform_width; }; template < class Base, int BitsOut, int BitsIn, class Char = typename boost::iterator_value::type // output character > class stateful_transform_width : public boost::iterator_adaptor< stateful_transform_width, Base, Char, single_pass_traversal_tag, Char> { friend class boost::iterator_core_access; typedef typename boost::iterator_adaptor< stateful_transform_width, Base, Char, single_pass_traversal_tag, Char> super_t; typedef stateful_transform_width this_t; typedef typename iterator_value::type base_value_type; Char fill(); Char dereference_impl() { if (!m_full) { m_current_value = fill(); m_full = true; } return m_current_value; } Char dereference() const { return const_cast(this)->dereference_impl(); } bool equal(const this_t &rhs) const { return this->base_reference() == rhs.base_reference(); } void increment() { m_displacement += BitsOut; while (m_displacement >= BitsIn) { m_displacement -= BitsIn; if (0 == m_displacement) m_bufferfull = false; if (!m_bufferfull) ++this->base_reference(); } // detect if the number of bits in the m_buffer is not enough // to encode a full 6-bit unit - read the next byte from the input if (m_displacement >= 0 && BitsIn - m_displacement < BitsOut) { // the following condition is compilable only with this variable typename this_t::base_type const &end_ = this->base_reference().end(); if (this->base_reference() != end_) { // read the next byte from the input or make it zero to // provide padding to encode th elast byte m_next_buffer = ++this->base_reference() != end_ ? *this->base_reference() : 0; m_nextfull = true; } // store the encoding state if we encountered the last byte if (this->base_reference() == end_) { typename Base::state_type &state = this->base_reference().state(); state.m_displacement = m_displacement; state.m_buffer = m_buffer; } } m_full = false; } // the most recent encoded character Char m_current_value; // number of bits left in current input character buffer unsigned int m_displacement; // value to be just encoded and a next value to be encoded base_value_type m_buffer, m_next_buffer; // flag to current output character is ready - just used to save time bool m_full; // flag to indicate that m_buffer and/or m_nextbuffer have data bool m_bufferfull, m_nextfull; public: template stateful_transform_width(BOOST_PFTO_WRAPPER(T) start) : super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), m_displacement(0), m_full(false), m_bufferfull(false), m_nextfull(false) {} stateful_transform_width(const stateful_transform_width &rhs) : super_t(rhs.base_reference()), m_current_value(rhs.m_current_value), m_displacement(rhs.m_displacement), m_buffer(rhs.m_buffer), m_next_buffer(rhs.m_next_buffer), m_full(rhs.m_full), m_bufferfull(rhs.m_bufferfull), m_nextfull(rhs.m_nextfull) {} }; template Char stateful_transform_width::fill() { typename Base::state_type &state = this->base_reference().state(); if (!state.empty()) { // initialize the m_buffer from the state and put the current input // byte to the m_next_buffer to make it follow right after m_displacement = state.m_displacement; m_buffer = state.m_buffer; m_bufferfull = true; m_next_buffer = *this->base_reference(); m_nextfull = true; state.clear(); } Char retval = 0; unsigned int missing_bits = BitsOut; for (;;) { unsigned int bcount; if (!m_bufferfull) { // fill the current m_buffer firstly from m_next_buffer if // available then read the input sequence if (m_nextfull) { m_buffer = m_next_buffer; m_nextfull = false; } else { m_buffer = *this->base_reference(); } m_bufferfull = true; bcount = BitsIn; } else bcount = BitsIn - m_displacement; unsigned int i = (std::min)(bcount, missing_bits); // shift interesting bits to least significant position unsigned int j = m_buffer >> (bcount - i); // strip off uninteresting bits // (note presumption of two's complement arithmetic) j &= ~(-(1 << i)); // append then interesting bits to the output value retval <<= i; retval |= j; missing_bits -= i; if (0 == missing_bits) break; // if we used a byte from the input sequence and not from the // prepared m_next_buffer, advance the input sequence iterator if (!m_nextfull) ++this->base_reference(); m_bufferfull = false; } return retval; } } // namespace iterators } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_ITERATORS_STATEFUL_TRANSFORM_WIDTH_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils/iterators/transform_width_with_state.hpp000066400000000000000000000172751256751517300331030ustar00rootroot00000000000000#ifndef BOOST_NETWORK_UTILS_ITERATORS_TRANSFORM_WIDTH_WITH_STATE_HPP #define BOOST_NETWORK_UTILS_ITERATORS_TRANSFORM_WIDTH_WITH_STATE_HPP #include #include #include #include // The class transform_width_with_state works like transform_width from // boost/archive/iterators if the collection of input values can be converted // to the output without padding the input with zeros. (The total input bit // count is divisible by the bit size of an output value.) It it cannot, the // partially encoded last value, which would have to be padded with zero, // is stored to the transform_width_state, which can be used later to // continue the encoding when another chunk of input values is available. // The end iterator is needed to detect the end transformation. // // The encoding state and the end iterator are owned by the transforming // iterator and they have to be passed to its constructor. Iterator adaptors // need to propagate the state and the end iterator to the transforming // iterator's constructor, which is inconvenient. namespace boost { namespace network { namespace utils { namespace iterators { template class transform_width_state { public: typedef Value value_type; transform_width_state() : m_displacement(0) {} transform_width_state(transform_width_state const &source) : m_displacement(source.m_displacement), m_buffer(source.m_buffer) {} bool empty() const { return bit_count() == 0; } void clear() { m_displacement = 0; } protected: unsigned short bit_count() const { return m_displacement > 0 ? BitsIn - m_displacement : 0; } private: unsigned short m_displacement; value_type m_buffer; template friend class transform_width_with_state; }; template ::type, // output character class State = transform_width_state< typename iterator_value::type, BitsOut, BitsIn> > class transform_width_with_state : public boost::iterator_adaptor< transform_width_with_state, Base, Char, single_pass_traversal_tag, Char> { friend class boost::iterator_core_access; typedef typename boost::iterator_adaptor< transform_width_with_state, Base, Char, single_pass_traversal_tag, Char> super_t; typedef transform_width_with_state this_t; typedef typename iterator_value::type base_value_type; Char fill(); Char dereference_impl() { if (!m_full) { m_current_value = fill(); m_full = true; } return m_current_value; } Char dereference() const { return const_cast(this)->dereference_impl(); } bool equal(const this_t &rhs) const { return this->base_reference() == rhs.base_reference(); } void increment() { m_displacement += BitsOut; while (m_displacement >= BitsIn) { m_displacement -= BitsIn; if (0 == m_displacement) m_bufferfull = false; if (!m_bufferfull) ++this->base_reference(); } // detect if the number of bits in the m_buffer is not enough // to encode a full 6-bit unit - read the next byte from the input if (m_displacement >= 0 && BitsIn - m_displacement < BitsOut) { // the following condition is compilable only with this variable typename this_t::base_type const &end_ = this->end(); if (this->base_reference() != end_) { // read the next byte from the input or make it zero to // provide padding to encode th elast byte m_next_buffer = ++this->base_reference() != end_ ? *this->base_reference() : 0; m_nextfull = true; } // store the encoding state if we encountered the last byte if (this->base_reference() == end_) { State &state = this->state(); state.m_displacement = m_displacement; state.m_buffer = m_buffer; } } m_full = false; } Base const &end() const { return m_end; } State const &state() const { return *m_state; } State &state() { return *m_state; } // iterator end for the iterator start sent to the constructor Base m_end; // encoding state to use and update State *m_state; // the most recent encoded character Char m_current_value; // number of bits left in current input character buffer unsigned int m_displacement; // value to be just encoded and a next value to be encoded base_value_type m_buffer, m_next_buffer; // flag to current output character is ready - just used to save time bool m_full; // flag to indicate that m_buffer and/or m_nextbuffer have data bool m_bufferfull, m_nextfull; public: template transform_width_with_state(BOOST_PFTO_WRAPPER(T) start, BOOST_PFTO_WRAPPER(T) end, State &state) : super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), m_end(end), m_state(&state), m_displacement(0), m_full(false), m_bufferfull(false), m_nextfull(false) {} template transform_width_with_state(BOOST_PFTO_WRAPPER(T) start) : super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), m_displacement(0), m_full(false), m_bufferfull(false), m_nextfull(false) {} transform_width_with_state(const transform_width_with_state &rhs) : super_t(rhs.base_reference()), m_end(rhs.m_end), m_state(rhs.m_state), m_current_value(rhs.m_current_value), m_displacement(rhs.m_displacement), m_buffer(rhs.m_buffer), m_next_buffer(rhs.m_next_buffer), m_full(rhs.m_full), m_bufferfull(rhs.m_bufferfull), m_nextfull(rhs.m_nextfull) {} }; template Char transform_width_with_state::fill() { State &state = this->state(); if (!state.empty()) { // initialize the m_buffer from the state and put the current input // byte to the m_next_buffer to make it follow right after m_displacement = state.m_displacement; m_buffer = state.m_buffer; m_bufferfull = true; m_next_buffer = *this->base_reference(); m_nextfull = true; state.clear(); } Char retval = 0; unsigned int missing_bits = BitsOut; for (;;) { unsigned int bcount; if (!m_bufferfull) { // fill the current m_buffer firstly from m_next_buffer if // available then read the input sequence if (m_nextfull) { m_buffer = m_next_buffer; m_nextfull = false; } else { m_buffer = *this->base_reference(); } m_bufferfull = true; bcount = BitsIn; } else bcount = BitsIn - m_displacement; unsigned int i = (std::min)(bcount, missing_bits); // shift interesting bits to least significant position unsigned int j = m_buffer >> (bcount - i); // strip off uninteresting bits // (note presumption of two's complement arithmetic) j &= ~(-(1 << i)); // append then interesting bits to the output value retval <<= i; retval |= j; missing_bits -= i; if (0 == missing_bits) break; // if we used a byte from the input sequence and not from the // prepared m_next_buffer, advance the input sequence iterator if (!m_nextfull) ++this->base_reference(); m_bufferfull = false; } return retval; } } // namespace iterators } // namespace utils } // namespace network } // namespace boost #endif // BOOST_NETWORK_UTILS_ITERATORS_TRANSFORM_WIDTH_WITH_STATE_HPP cpp-netlib-0.11.2-final/libs/network/experiment/utils_base64_experiment.cpp000066400000000000000000000114741256751517300270140ustar00rootroot00000000000000#include #include #include #include "utils/base64-standalone.hpp" // Since we're having issues with libc++ on OS X we're excluding this in the // meantime if we're using libc++ #ifndef _LIBCPP_VERSION #include "utils/base64-stateless.hpp" #include "utils/base64-stateful_buffer.hpp" #endif #include "utils/base64-stateful_iterator.hpp" #include "utils/base64-stateful_transform.hpp" #include #include #include #include #include #include // the main entry point does nothing; the tests are run by constructors // of testing classes, which are executed by global variables int main(int argc, char const* argv[]) { return 0; } using namespace boost::network::utils; // macros to build names of test classes ans gobal runner variables #define stringify_internal(x) #x #define stringify(x) stringify_internal(x) #define concatenate_internal(x, y) x##y #define concatenate(x, y) concatenate_internal(x, y) #ifdef NDEBUG // testing block sizes (im MB) which let the tests run approximately // 5s on my machine in the optimized mode #define single_block_size 160 #define multiple_block_size 320 #define multiple_block_count 1280 #else // testing block sizes (im MB) which let the tests run approximately // 5s on my machine in the not optimized mode #define single_block_size 16 #define multiple_block_size 64 #define multiple_block_count 256 #endif // the class name of a test suite; base64 has to be defined as a namespace // name with an alternative implementation of the base64 encoding interface #define test_name concatenate(base64, _test) // the code which actually performs the encoding; base64 has to be defined // as a namespace name - see above #define encode_single_block std::string result = base64::encode(buffer) #define encode_multiple_blocks \ std::string result; \ std::back_insert_iterator result_encoder(result); \ base64::state rest; \ for (unsigned block_index = 0; block_index < buffers.size(); \ ++block_index) { \ std::vector const& buffer = buffers[block_index]; \ base64::encode(buffer.begin(), buffer.end(), result_encoder, rest); \ } \ base64::encode_rest(result_encoder, rest) // testing the code from experimental/base64-stateless.hpp // NOTE(dberris): Only do this if we're NOT using libc++. #ifndef _LIBCPP_VERSION #define base64 base64_stateless #include "utils_base64_experiment.ipp" #undef base64 // enable the second test case, which encodes the input buffer chunk by chunk // and remembers the encoding state to be able to continue #define base64_with_state // testing the code from experimental/base64-stateful_buffer.hpp #define base64 base64_stateful_buffer #include "utils_base64_experiment.ipp" #undef base64 #endif // _LIBCPP_VERSION // testing the code from experimental/base64-stateful_transform.hpp #define base64 base64_stateful_transform #include "utils_base64_experiment.ipp" #undef base64 // testing the code from experimental/base64-stateful_iterator.hpp #define base64 base64_stateful_iterator #include "utils_base64_experiment.ipp" #undef base64 // testing the code from experimental/base64-standalone.hpp, // which has become the code in boost/network/utils/base64/encode.hpp #define base64 base64_standalone #include "utils_base64_experiment.ipp" #undef base64 // redefine the testing code to use the iostream implementation from // boost/network/utils/base64/encode-io.hpp which depends on the // interface from boost/network/utils/base64/encode.hpp #undef test_name #undef encode_single_block #undef encode_multiple_blocks #define test_name concatenate(concatenate(base64, _standalone_io), _test) #define encode_single_block \ std::stringstream result; \ result << base64::io::encode(buffer) << base64::io::encode_rest #define encode_multiple_blocks \ std::stringstream result; \ for (unsigned block_index = 0; block_index < buffers.size(); \ ++block_index) { \ std::vector const& buffer = buffers[block_index]; \ result << base64::io::encode(buffer.begin(), buffer.end()); \ } \ result << base64::io::encode_rest // testing the iostream implementation with the code from // boost/network/utils/base64/encode.hpp #define base64 base64 #include "utils_base64_experiment.ipp" #undef base64 cpp-netlib-0.11.2-final/libs/network/experiment/utils_base64_experiment.ipp000066400000000000000000000033651256751517300270220ustar00rootroot00000000000000class test_name { void test_single_block(); void test_multiple_blocks(); public: test_name() { std::cout << "Executing " stringify(test_name) ":" << std::endl; test_single_block(); test_multiple_blocks(); } }; test_name concatenate(run_, test_name); void test_name::test_single_block() { std::cout << " Encoding " << single_block_size << " MB buffer took "; // Fill a single vector with random bytes. std::vector buffer(single_block_size * 1024 * 1024); for (std::vector::iterator current = buffer.begin(); current != buffer.end(); ++current) *current = static_cast(rand() % 255); // Encode the single vector to a single BASE64 string. clock_t start = clock(); encode_single_block; clock_t end = clock(); std::cout << (double)(end - start) / CLOCKS_PER_SEC << "s." << std::endl; } void test_name::test_multiple_blocks() { #ifdef base64_with_state std::cout << " Encoding " << multiple_block_count << " x " << multiple_block_size << " KB buffers took "; // Fill multiple vectors with random bytes. std::vector > buffers(multiple_block_count); for (unsigned block_index = 0; block_index < buffers.size(); ++block_index) { std::vector& buffer = buffers[block_index]; buffer.resize(multiple_block_size * 1024); for (std::vector::iterator current = buffer.begin(); current != buffer.end(); ++current) *current = static_cast(rand() % 255); } // Encode the multiple vectors to a single BASE64 string. clock_t start = clock(); encode_multiple_blocks; clock_t end = clock(); std::cout << (double)(end - start) / CLOCKS_PER_SEC << "s." << std::endl; #endif } cpp-netlib-0.11.2-final/libs/network/experiment/utils_base64_experiment.txt000066400000000000000000000046041256751517300270460ustar00rootroot00000000000000Benchmark results from GCC 4.6.4 without any optimization (no switches): Executing base64_stateless_test: Encoding 16 MB buffer took 4.81s. Executing base64_stateful_buffer_test: Encoding 16 MB buffer took 4.93s. Encoding 256 x 64 KB buffers took 4.92s. Executing base64_stateful_transform_test: Encoding 16 MB buffer took 5.32s. Encoding 256 x 64 KB buffers took 5.25s. Executing base64_stateful_iterator_test: Encoding 16 MB buffer took 7.03s. Encoding 256 x 64 KB buffers took 7.02s. Executing base64_standalone_test: Encoding 16 MB buffer took 0.93s. Encoding 256 x 64 KB buffers took 1.01s. Executing base64_standalone_io_test: Encoding 16 MB buffer took 2.31s. Encoding 256 x 64 KB buffers took 2.32s. Benchmark results from GCC 4.6.4 with the -O3 optimization; the processed data were 10 times bigger than for the test run without any optimization: Executing base64_stateless_test: Encoding 160 MB buffer took 3.42s. Executing base64_stateful_buffer_test: Encoding 160 MB buffer took 3.69s. Encoding 1280 x 320 KB buffers took 9.43s. Executing base64_stateful_transform_test: Encoding 160 MB buffer took 4.71s. Encoding 1280 x 320 KB buffers took 12.27s. Executing base64_stateful_iterator_test: Encoding 160 MB buffer took 4.65s. Encoding 1280 x 320 KB buffers took 11.92s. Executing base64_standalone_test: Encoding 160 MB buffer took 1.46s. Encoding 1280 x 320 KB buffers took 4.09s. Executing base64_standalone_io_test: Encoding 160 MB buffer took 3.93s. Encoding 1280 x 320 KB buffers took 10.18s. Testing the base64_stateless was done for the sake of completeness just to test the pure boost implementation only; state is needed for chunked encoding. The three different base64_stateful_xxx implementations are comparable; the base64_stateful_iterator may have spent more time in copy constructors, because the state is owned lower - by the transformed iterator adaptor. The iostream interface brings noticeable overhead, especially if the encoding state (stored in the internal extensible array of the output stream) is used extensively. The boost transforming iterators are not enough to implement BASE64 encoding of a chunked input. Taking the additional code into consideration, the amount of code for the non-boost base64_standalone implementation is not so different and offers better performance. cpp-netlib-0.11.2-final/libs/network/src/000077500000000000000000000000001256751517300201445ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/src/CMakeLists.txt000066400000000000000000000042721256751517300227110ustar00rootroot00000000000000# Copyright (c) Glyn Matthews 2011. # Copyright 2011 Dean Michael Berris (dberris@google.com) # Copyright 2011 Google, Inc. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) file(GLOB_RECURSE CPP-NETLIB_HEADERS "${CPP-NETLIB_SOURCE_DIR}/boost/" "*.hpp") set(CPP-NETLIB_URI_SRCS uri/uri.cpp uri/schemes.cpp) add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS}) set_target_properties(cppnetlib-uri PROPERTIES VERSION ${CPPNETLIB_VERSION_STRING} SOVERSION ${CPPNETLIB_VERSION_MAJOR} PUBLIC_HEADER "${CPP-NETLIB_HEADERS}") install(TARGETS cppnetlib-uri EXPORT cppnetlibTargets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) set_target_properties(cppnetlib-server-parsers PROPERTIES VERSION ${CPPNETLIB_VERSION_STRING} SOVERSION ${CPPNETLIB_VERSION_MAJOR} PUBLIC_HEADER "${CPP-NETLIB_HEADERS}") install(TARGETS cppnetlib-server-parsers EXPORT cppnetlibTargets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) set(CPP-NETLIB_HTTP_CLIENT_SRCS client.cpp) add_library(cppnetlib-client-connections ${CPP-NETLIB_HTTP_CLIENT_SRCS}) set_target_properties(cppnetlib-client-connections PROPERTIES VERSION ${CPPNETLIB_VERSION_STRING} SOVERSION ${CPPNETLIB_VERSION_MAJOR} PUBLIC_HEADER "${CPP-NETLIB_HEADERS}") if (OPENSSL_FOUND) target_link_libraries(cppnetlib-client-connections ${OPENSSL_LIBRARIES}) endif () if (Boost_FOUND) target_link_libraries(cppnetlib-client-connections ${Boost_LIBRARIES}) endif () install(TARGETS cppnetlib-client-connections EXPORT cppnetlibTargets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) cpp-netlib-0.11.2-final/libs/network/src/client.cpp000066400000000000000000000010751256751517300221310ustar00rootroot00000000000000 // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifdef BOOST_NETWORK_NO_LIB #warn Building the library even with BOOST_NETWORK_NO_LIB defined. #undef BOOST_NETWORK_NO_LIB #endif #include #ifdef BOOST_NETWORK_ENABLE_HTTPS #include #endif cpp-netlib-0.11.2-final/libs/network/src/server_request_parsers_impl.cpp000066400000000000000000000005031256751517300265040ustar00rootroot00000000000000// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifdef BOOST_NETWORK_NO_LIB #undef BOOST_NETWORK_NO_LIB #endif #include cpp-netlib-0.11.2-final/libs/network/src/uri/000077500000000000000000000000001256751517300207435ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/src/uri/schemes.cpp000066400000000000000000000036141256751517300231020ustar00rootroot00000000000000// Copyright 2012 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace network { namespace uri { namespace { static boost::unordered_set hierarchical_schemes_; static boost::unordered_set opaque_schemes_; bool register_hierarchical_schemes() { hierarchical_schemes_.insert("http"); hierarchical_schemes_.insert("https"); hierarchical_schemes_.insert("shttp"); hierarchical_schemes_.insert("ftp"); hierarchical_schemes_.insert("file"); hierarchical_schemes_.insert("dns"); hierarchical_schemes_.insert("nfs"); hierarchical_schemes_.insert("imap"); hierarchical_schemes_.insert("nntp"); hierarchical_schemes_.insert("pop"); hierarchical_schemes_.insert("rsync"); hierarchical_schemes_.insert("snmp"); hierarchical_schemes_.insert("telnet"); hierarchical_schemes_.insert("svn"); hierarchical_schemes_.insert("svn+ssh"); hierarchical_schemes_.insert("git"); hierarchical_schemes_.insert("git+ssh"); return true; } bool register_opaque_schemes() { opaque_schemes_.insert("mailto"); opaque_schemes_.insert("news"); opaque_schemes_.insert("im"); opaque_schemes_.insert("sip"); opaque_schemes_.insert("sms"); opaque_schemes_.insert("xmpp"); return true; } static bool hierarchical = register_hierarchical_schemes(); static bool opaque = register_opaque_schemes(); } // namespace bool hierarchical_schemes::exists(const std::string &scheme) { return hierarchical_schemes_.end() != hierarchical_schemes_.find(scheme); } bool opaque_schemes::exists(const std::string &scheme) { return opaque_schemes_.end() != opaque_schemes_.find(scheme); } } // namespace uri } // namespace network } // namespace boost cpp-netlib-0.11.2-final/libs/network/src/uri/uri.cpp000066400000000000000000000003741256751517300222520ustar00rootroot00000000000000// Copyright 2012 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include cpp-netlib-0.11.2-final/libs/network/test/000077500000000000000000000000001256751517300203345ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/test/CMakeLists.txt000066400000000000000000000032421256751517300230750ustar00rootroot00000000000000# Copyright (c) Dean Michael Berris 2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) add_subdirectory(uri) add_subdirectory(http) if (Boost_FOUND) set( TESTS message_test message_transform_test utils_thread_pool # utils_base64_test -- turn on when ready. ) foreach (test ${TESTS}) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-${test} ${test}.cpp) add_dependencies(cpp-netlib-${test} cppnetlib-uri) target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-${test} ws2_32 wsock32) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(cpp-netlib-${test} rt) endif() set_target_properties(cpp-netlib-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) # Also copy the server directory to the root of the build directory. file(COPY server DESTINATION ${CPP-NETLIB_BINARY_DIR}/libs/network/test/) endif() cpp-netlib-0.11.2-final/libs/network/test/client_server_include_failure.cpp000066400000000000000000000014361256751517300271220ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE Client and server includes #include // // The problem here is a bizarre compilation failure in including // these two files, and instantiating a client. It's described at // http://github.com/cpp-netlib/cpp-netlib/issues#issue/13 // #include #include BOOST_AUTO_TEST_CASE(test1) { typedef boost::network::http::basic_client< boost::network::http::tags::http_keepalive_8bit_udp_resolve, 1, 1> http_client; http_client client; } cpp-netlib-0.11.2-final/libs/network/test/http/000077500000000000000000000000001256751517300213135ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/test/http/CMakeLists.txt000066400000000000000000000073051256751517300240600ustar00rootroot00000000000000 # Copyright 2010 Dean Michael Berris. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) if (OPENSSL_FOUND) include_directories( ${OPENSSL_INCLUDE_DIR} ) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() if (Boost_FOUND) set ( TESTS response_incremental_parser_test request_incremental_parser_test request_linearize_test ) foreach ( test ${TESTS} ) add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-http-${test} ws2_32) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(cpp-netlib-http-${test} rt) endif() set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) set ( TESTS client_constructor_test client_get_test client_get_different_port_test client_get_timeout_test client_get_streaming_test ) foreach ( test ${TESTS} ) add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-uri cppnetlib-client-connections) target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-http-${test} ws2_32) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(cpp-netlib-http-${test} rt) endif() set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) set ( SERVER_API_TESTS server_constructor_test server_async_run_stop_concurrency server_header_parser_test ) foreach ( test ${SERVER_API_TESTS} ) add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-http-${test} ws2_32 wsock32) endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(cpp-netlib-http-${test} rt) endif() set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) endif() cpp-netlib-0.11.2-final/libs/network/test/http/client_constructor_test.cpp000066400000000000000000000023501256751517300270010ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP 1.0 Client Constructor Test #include #include #include "client_types.hpp" namespace http = boost::network::http; BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, client, client_types) { typename client::options options; client instance; client instance2( options.io_service(boost::make_shared())); } BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client_types) { typename client::options options; client instance(options.follow_redirects(true).cache_resolved(true)); client instance2( options.openssl_certificate("foo").openssl_verify_path("bar")); client instance3( options.openssl_certificate_file("foo").openssl_private_key_file("bar")); client instance4( options.follow_redirects(true) .io_service(boost::make_shared()) .cache_resolved(true)); } cpp-netlib-0.11.2-final/libs/network/test/http/client_get_different_port_test.cpp000066400000000000000000000016271256751517300302730ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Client Get Different Port Test #include #include #include "client_types.hpp" namespace net = boost::network; namespace http = boost::network::http; BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port, client, client_types) { typename client::request request("http://www.boost.org:80/"); client client_; typename client::response response_ = client_.get(request); typename net::headers_range::type range = headers(response_)["Content-Type"]; BOOST_CHECK(boost::begin(range) != boost::end(range)); BOOST_CHECK(body(response_).size() != 0); } cpp-netlib-0.11.2-final/libs/network/test/http/client_get_streaming_test.cpp000066400000000000000000000032211256751517300272420ustar00rootroot00000000000000// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test #include #include #include #include "client_types.hpp" namespace net = boost::network; namespace http = boost::network::http; struct body_handler { explicit body_handler(std::string& body) : body(body) {} BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { body.append(boost::begin(range), boost::end(range)); } std::string& body; }; BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, async_only_client_types) { typename client::request request("http://www.boost.org"); typename client::response response; typename client::string_type body_string; typename client::string_type dummy_body; body_handler handler_instance(body_string); { client client_; BOOST_CHECK_NO_THROW(response = client_.get(request, handler_instance)); typename net::headers_range::type range = headers(response)["Content-Type"]; BOOST_CHECK(!boost::empty(range)); BOOST_CHECK_EQUAL(body(response).size(), 0u); BOOST_CHECK_EQUAL(response.version().substr(0, 7), std::string("HTTP/1.")); BOOST_CHECK_EQUAL(response.status(), 200u); BOOST_CHECK_EQUAL(response.status_message(), std::string("OK")); dummy_body = body(response); } BOOST_CHECK(dummy_body == typename client::string_type()); } cpp-netlib-0.11.2-final/libs/network/test/http/client_get_test.cpp000066400000000000000000000042521256751517300251760ustar00rootroot00000000000000// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP 1.0 Get Test #include #include #include "client_types.hpp" namespace net = boost::network; namespace http = boost::network::http; BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, client, client_types) { typename client::request request("http://www.boost.org"); client client_; typename client::response response; BOOST_REQUIRE_NO_THROW(response = client_.get(request)); typename net::headers_range::type range = headers(response)["Content-Type"]; BOOST_CHECK(!boost::empty(range)); BOOST_REQUIRE_NO_THROW(BOOST_CHECK(body(response).size() != 0)); BOOST_CHECK_EQUAL(response.version().substr(0, 7), std::string("HTTP/1.")); BOOST_CHECK_EQUAL(response.status(), 200u); BOOST_CHECK_EQUAL(response.status_message(), std::string("OK")); } #ifdef BOOST_NETWORK_ENABLE_HTTPS BOOST_AUTO_TEST_CASE_TEMPLATE(https_client_get_test, client, client_types) { typename client::request request("https://www.google.com/"); client client_; typename client::response response_ = client_.get(request); typename net::headers_range::type range = headers(response_)["Content-Type"]; BOOST_CHECK(boost::begin(range) != boost::end(range)); BOOST_CHECK(body(response_).size() != 0); } #endif BOOST_AUTO_TEST_CASE_TEMPLATE(http_temp_client_get_test, client, client_types) { typename client::request request("http://www.google.co.kr"); typename client::response response; BOOST_REQUIRE_NO_THROW(response = client().get(request)); typename net::headers_range::type range = headers(response)["Content-Type"]; BOOST_CHECK(!boost::empty(range)); BOOST_REQUIRE_NO_THROW(BOOST_CHECK(body(response).size() != 0)); BOOST_CHECK_EQUAL(response.version().substr(0, 7), std::string("HTTP/1.")); BOOST_CHECK_EQUAL(response.status(), 200u); BOOST_CHECK_EQUAL(response.status_message(), std::string("OK")); } cpp-netlib-0.11.2-final/libs/network/test/http/client_get_timeout_test.cpp000066400000000000000000000042741256751517300267500ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Client Get Timeout Test #include #include #include #include "client_types.hpp" #include "http_test_server.hpp" struct localhost_server_fixture { localhost_server_fixture() { if (!server.start()) { std::cout << "Failed to start HTTP server for test!" << std::endl; std::abort(); } } ~localhost_server_fixture() { if (!server.stop()) { std::cout << "Failed to stop HTTP server for test!" << std::endl; std::abort(); } } http_test_server server; }; BOOST_GLOBAL_FIXTURE(localhost_server_fixture); BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, client, client_types) { typename client::request request("http://localhost:12121/"); typename client::response response_; client client_; boost::uint16_t port_ = port(request); typename client::response::string_type temp; BOOST_CHECK_EQUAL(12121, port_); BOOST_CHECK_THROW(response_ = client_.get(request); temp = body(response_); , std::exception); } BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_with_options, client, client_types) { typename client::request request("http://localhost:8000/cgi-bin/sleep.py?3"); typename client::response response; typename client::options options; client client_(options.timeout(1)); typename client::response::string_type temp; BOOST_CHECK_THROW(response = client_.get(request); temp = body(response); , std::exception); } #ifdef BOOST_NETWORK_ENABLE_HTTPS BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test_timeout_with_options, client, client_types) { typename client::request request("https://localhost:8000/cgi-bin/sleep.py?3"); typename client::response response; typename client::options options; client client_(options.timeout(1)); typename client::response::string_type temp; BOOST_CHECK_THROW(response = client_.get(request); temp = body(response); , std::exception); } #endif cpp-netlib-0.11.2-final/libs/network/test/http/client_include_inlined.cpp000066400000000000000000000012121256751517300264760ustar00rootroot00000000000000// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_NETWORK_NO_LIB #include int main(int argc, char* argv[]) { using namespace boost; using namespace boost::network; http::client c; http::client::request req("http://www.boost.org/"); try { http::client::response res = c.get(req); } catch (...) { // ignore the error, we just want to make sure // the interface works inlined. } return 0; } cpp-netlib-0.11.2-final/libs/network/test/http/client_localhost_normal_test.cpp000066400000000000000000000300721256751517300277560ustar00rootroot00000000000000// // Copyright Divye Kapoor 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Changes by Kim Grasman 2008 // Changes by Dean Michael Berris 2008, 2010 #define BOOST_TEST_MODULE http 1.0 localhost tests #include #include #include #include #include #include #include #include #include #include "http_test_server.hpp" using std::cout; using std::endl; namespace { const std::string base_url = "http://localhost:8000"; const std::string cgi_url = base_url + "/cgi-bin/requestinfo.py"; struct running_server_fixture { // NOTE: Can't use BOOST_REQUIRE_MESSAGE here, as Boost.Test data structures // are not fully set up when the global fixture runs. running_server_fixture() { if (!server.start()) cout << "Failed to start HTTP server for test!" << endl; } ~running_server_fixture() { if (!server.stop()) cout << "Failed to stop HTTP server for test!" << endl; } http_test_server server; }; std::size_t readfile(std::ifstream& file, std::vector& buffer) { using std::ios; std::istreambuf_iterator src(file); std::istreambuf_iterator eof; std::copy(src, eof, std::back_inserter(buffer)); return buffer.size(); } std::map parse_headers(std::string const& body) { std::map headers; std::istringstream stream(body); while (stream.good()) { std::string line; std::getline(stream, line); if (!stream.eof()) { std::size_t colon = line.find(':'); if (colon != std::string::npos) { std::string header = line.substr(0, colon); std::string value = line.substr(colon + 2); headers[header] = value; } } } return headers; } std::string get_content_length(std::string const& content) { return boost::lexical_cast(content.length()); } } #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) // Uncomment the below if you're running Python pre-2.6. There was a bug // in the Python HTTP server for earlier versions that causes this test // case to fail. // BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(text_query_preserves_crlf, 2); #endif BOOST_GLOBAL_FIXTURE(running_server_fixture); BOOST_AUTO_TEST_CASE(body_test) { // Tests presence of body in http responses using namespace boost::network; http::client::request request_(base_url); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_content_type_test) { // Tests correct parsing of the content-type header sent by the server using namespace boost::network; http::client::request request_(base_url); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); BOOST_CHECK(boost::begin(range)->second == "text/html"); } BOOST_AUTO_TEST_CASE(binary_content_type_test) { // Tests correct parsing of content-type for binary files such as .zip files using namespace boost::network; http::client::request request_(base_url + "/boost.jpg"); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); BOOST_CHECK(boost::begin(range)->second == "image/jpeg"); } BOOST_AUTO_TEST_CASE(content_length_header_test) { // Uses the test.xml file to ensure that the file was received at the correct // length for a text encoding using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { // Tests proper transfer of a text file using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); http::client::response::string_type body_ = body(response_); BOOST_CHECK(body(response_).size() != 0); using std::ios; std::ifstream file("libs/network/test/server/test.xml", ios::in | ios::binary); if (!file) { file.clear(); file.open("server/test.xml", ios::in | ios::binary); } BOOST_REQUIRE_MESSAGE(file, "Could not open local test.xml"); std::vector memblock; std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); BOOST_CHECK_EQUAL(body_.size(), size); if (body(response_).size() == size) { std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL( boost::numeric_cast(diff_pos.first - memblock.begin()), size); } } BOOST_AUTO_TEST_CASE(binary_file_query) { // Tests proper transfer of a binary image using namespace boost::network; http::client::request request_(base_url + "/boost.jpg"); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); http::client::response::string_type body_ = body(response_); BOOST_CHECK(body_.size() != 0); using std::ios; std::ifstream file("libs/network/test/server/boost.jpg", ios::in | ios::binary); if (!file) { file.clear(); file.open("server/boost.jpg", ios::in | ios::binary); } BOOST_REQUIRE_MESSAGE(file, "Could not open boost.jpg locally"); std::vector memblock; std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); BOOST_CHECK_EQUAL(body_.size(), size); std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL( boost::numeric_cast(diff_pos.first - memblock.begin()), size); } BOOST_AUTO_TEST_CASE(cgi_query) { // Get a dynamic request with no Content-Length header // Ensure that we have a body using namespace boost::network; http::client::request req(cgi_url + "?query=1"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.get(req)); BOOST_CHECK(body(r).size() != 0); BOOST_CHECK(boost::empty(headers(r)["Content-Length"])); } BOOST_AUTO_TEST_CASE(cgi_multi_line_headers) { using namespace boost::network; http::client::request req(base_url + "/cgi-bin/multiline-header.py?query=1"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.get(req)); BOOST_CHECK(body(r).size() != 0); BOOST_CHECK(boost::empty(headers(r)["Content-Type"])); headers_range::type range = headers(r)["X-CppNetlib-Test"]; BOOST_REQUIRE(boost::begin(range) != boost::end(range)); BOOST_REQUIRE(distance(range) == 2); BOOST_CHECK_EQUAL(boost::begin(range)->second, std::string("multi-line-header")); BOOST_CHECK_EQUAL((++boost::begin(range))->second, std::string("that-should-concatenate")); } BOOST_AUTO_TEST_CASE(file_not_found) { // Request for a non existing file. // Ensure that we have a body even in the presence of an error response using namespace boost::network; http::client::request req(base_url + "/file_not_found"); http::client c; http::client::response r = c.get(req); BOOST_CHECK(body(r).size() != 0); } BOOST_AUTO_TEST_CASE(head_test) { using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_; BOOST_REQUIRE_NO_THROW(response_ = client_.head(request_)); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); BOOST_CHECK(body(response_).size() == 0); } BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { // This test checks that the headers echoed through echo_headers.py // are in fact the same as what are sent through the POST request using namespace boost::network; const std::string postdata = "empty"; const std::string content_length = get_content_length(postdata); const std::string content_type = "application/x-www-form-urlencoded"; http::client::request req(base_url + "/cgi-bin/echo_headers.py"); req << header("Content-Length", content_length); req << header("Content-Type", content_type); req << body(postdata); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req)); std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], content_length); BOOST_CHECK_EQUAL(headers["content-type"], content_type); } BOOST_AUTO_TEST_CASE(post_with_implicit_headers) { // This test checks that post(request, body) derives Content-Length // and Content-Type using namespace boost::network; const std::string postdata = "empty"; http::client::request req(base_url + "/cgi-bin/echo_headers.py"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); BOOST_CHECK_EQUAL(headers["content-type"], "x-application/octet-stream"); } BOOST_AUTO_TEST_CASE(post_with_explicit_content_type) { // This test checks that post(request, content_type, body) derives // Content-Length, // and keeps Content-Type using namespace boost::network; const std::string postdata = "empty"; const std::string content_type = "application/x-my-content-type"; http::client::request req(base_url + "/cgi-bin/echo_headers.py"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, content_type, postdata)); std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); BOOST_CHECK_EQUAL(headers["content-type"], content_type); } BOOST_AUTO_TEST_CASE(post_body_default_content_type) { // This test checks that post(request, body) gets the post data // through to the server using namespace boost::network; const std::string postdata = "firstname=bill&lastname=badger"; http::client::request req(base_url + "/cgi-bin/echo_body.py"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); http::client::response::string_type body_ = body(r); BOOST_CHECK_EQUAL(postdata, body_); } BOOST_AUTO_TEST_CASE(post_with_custom_headers) { // This test checks that custom headers pass through to the server // when posting using namespace boost::network; http::client::request req(base_url + "/cgi-bin/echo_headers.py"); req << header("X-Cpp-Netlib", "rocks!"); http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, std::string())); std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["x-cpp-netlib"], "rocks!"); } cpp-netlib-0.11.2-final/libs/network/test/http/client_localhost_ssl_test.cpp000066400000000000000000000271371256751517300272770ustar00rootroot00000000000000// // Copyright Divye Kapoor 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) // // Changes by Kim Grasman 2008 // Changes by Dean Michael Berris 2008, 2009 #define BOOST_TEST_MODULE https 1.0 localhost tests #include #include #include #include #include #include #include #include #define HTTPS_SERVER_TEST #include "http_test_server.hpp" using std::cout; using std::endl; namespace { const std::string base_url = "https://localhost:8443"; const std::string cgi_url = base_url + "/cgi-bin/requestinfo.py"; struct running_server_fixture { // NOTE: Can't use BOOST_REQUIRE_MESSAGE here, as Boost.Test data structures // are not fully set up when the global fixture runs. running_server_fixture() { if (!server.start()) cout << "Failed to start HTTP server for test!" << endl; } ~running_server_fixture() { if (!server.stop()) cout << "Failed to stop HTTP server for test!" << endl; } http_test_server server; }; std::size_t readfile(std::ifstream& file, std::vector& buffer) { using std::ios; std::istreambuf_iterator src(file); std::istreambuf_iterator eof; std::copy(src, eof, std::back_inserter(buffer)); return buffer.size(); } } #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) // Uncomment the below if you're running Python pre-2.6. There was a bug // in the Python HTTP server for earlier versions that causes this test // case to fail. // BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(text_query_preserves_crlf, 2); #endif BOOST_GLOBAL_FIXTURE(running_server_fixture); BOOST_AUTO_TEST_CASE(body_test) { // Tests presence of body in http responses using namespace boost::network; http::client::request request_(base_url); http::client client_; http::client::response response_ = client_.get(request_); BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_content_type_test) { // Tests correct parsing of the content-type header sent by the server using namespace boost::network; http::client::request request_(base_url); http::client client_; http::client::response response_ = client_.get(request_); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); BOOST_CHECK(boost::begin(range)->second == "text/html"); } BOOST_AUTO_TEST_CASE(binary_content_type_test) { // Tests correct parsing of content-type for binary files such as .zip files using namespace boost::network; http::client::request request_(base_url + "/boost.jpg"); http::client client_; http::client::response response_ = client_.get(request_); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); BOOST_CHECK(boost::begin(range)->second == "image/jpeg"); } BOOST_AUTO_TEST_CASE(content_length_header_test) { // Uses the test.xml file to ensure that the file was received at the correct // length for a text encoding using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_ = client_.get(request_); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { // Tests proper transfer of a text file using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_ = client_.get(request_); http::client::response::string_type body_ = body(response_); BOOST_CHECK(body_.size() != 0); using std::ios; std::ifstream file("libs/network/test/server/test.xml", ios::in | ios::binary); if (!file) { file.clear(); file.open("server/test.xml", ios::in | ios::binary); } BOOST_REQUIRE_MESSAGE(file, "Could not open local test.xml"); std::vector memblock; std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); BOOST_CHECK_EQUAL(body(response_).size(), size); if (body(response_).size() == size) { std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL( boost::numeric_cast(diff_pos.first - memblock.begin()), size); } } BOOST_AUTO_TEST_CASE(binary_file_query) { // Tests proper transfer of a binary image using namespace boost::network; http::client::request request_(base_url + "/boost.jpg"); http::client client_; http::client::response response_; BOOST_CHECK_NO_THROW(response_ = client_.get(request_)); http::client::response::string_type body_ = body(response_); BOOST_CHECK(body_.size() != 0); using std::ios; std::ifstream file("libs/network/test/server/boost.jpg", ios::in | ios::binary); if (!file) { file.clear(); file.open("server/boost.jpg", ios::in | ios::binary); } BOOST_REQUIRE_MESSAGE(file, "Could not open boost.jpg locally"); std::vector memblock; std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); BOOST_CHECK_EQUAL(body(response_).size(), size); std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL( boost::numeric_cast(diff_pos.first - memblock.begin()), size); } // BOOST_AUTO_TEST_CASE(cgi_query) { // // Get a dynamic request with no Content-Length header // // Ensure that we have a body // using namespace boost::network; // // http::client::request req(cgi_url + "?query=1"); // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.get(req)); // BOOST_CHECK(body(r).size() != 0); // BOOST_CHECK(headers(r)["Content-Type"].begin() != // headers(r)["Content-Type"].end()); //} // // BOOST_AUTO_TEST_CASE(cgi_multi_line_headers) { // using namespace boost::network; // // http::client::request req(base_url + // "/cgi-bin/multiline-header.py?query=1"); // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.get(req)); // BOOST_CHECK(body(r).size() != 0); // BOOST_CHECK(headers(r)["Content-Type"].begin() != // headers(r)["Content-Type"].end()); // headers_range::type // range=headers(r)["X-CppNetlib-Test"]; // BOOST_REQUIRE(boost::begin(range) != boost::end(range)); // BOOST_REQUIRE(distance(range) == 2); // BOOST_CHECK_EQUAL(boost::begin(range)->second, // std::string("multi-line-header")); // BOOST_CHECK_EQUAL((++boost::begin(range))->second, // std::string("that-should-concatenate")); //} BOOST_AUTO_TEST_CASE(file_not_found) { // Request for a non existing file. // Ensure that we have a body even in the presence of an error response using namespace boost::network; http::client::request req(base_url + "/file_not_found"); http::client c; http::client::response r = c.get(req); BOOST_CHECK(body(r).size() != 0); } BOOST_AUTO_TEST_CASE(head_test) { using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; http::client::response response_ = client_.head(request_); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); BOOST_CHECK(body(response_).size() == 0); } // BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { // // This test checks that the headers echoed through echo_headers.py // // are in fact the same as what are sent through the POST request // using namespace boost::network; // // const std::string postdata = "empty"; // const std::string content_length = get_content_length(postdata); // const std::string content_type = "application/x-www-form-urlencoded"; // // http::client::request req(base_url + "/cgi-bin/echo_headers.py"); // req << header("Content-Length", content_length); // req << header("Content-Type", content_type); // req << body(postdata); // // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.post(req)); // // std::map headers = parse_headers(body(r)); // BOOST_CHECK_EQUAL(headers["content-length"], content_length); // BOOST_CHECK_EQUAL(headers["content-type"], content_type); //} // // BOOST_AUTO_TEST_CASE(post_with_implicit_headers) { // // This test checks that post(request, body) derives Content-Length // // and Content-Type // using namespace boost::network; // // const std::string postdata = "empty"; // // http::client::request req(base_url + "/cgi-bin/echo_headers.py"); // // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); // // std::map headers = parse_headers(body(r)); // BOOST_CHECK_EQUAL(headers["content-length"], // get_content_length(postdata)); // BOOST_CHECK_EQUAL(headers["content-type"], "x-application/octet-stream"); //} // // BOOST_AUTO_TEST_CASE(post_with_explicit_content_type) { // // This test checks that post(request, content_type, body) derives // Content-Length, // // and keeps Content-Type // using namespace boost::network; // // const std::string postdata = "empty"; // const std::string content_type = "application/x-my-content-type"; // // http::client::request req(base_url + "/cgi-bin/echo_headers.py"); // // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.post(req, content_type, postdata)); // // std::map headers = parse_headers(body(r)); // BOOST_CHECK_EQUAL(headers["content-length"], // get_content_length(postdata)); // BOOST_CHECK_EQUAL(headers["content-type"], content_type); //} // // BOOST_AUTO_TEST_CASE(post_body_default_content_type) { // // This test checks that post(request, body) gets the post data // // through to the server // using namespace boost::network; // // const std::string postdata = "firstname=bill&lastname=badger"; // // http::client::request req(base_url + "/cgi-bin/echo_body.py"); // // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); // // BOOST_CHECK_EQUAL(postdata, body(r)); //} // // BOOST_AUTO_TEST_CASE(post_with_custom_headers) { // // This test checks that custom headers pass through to the server // // when posting // using namespace boost::network; // // http::client::request req(base_url + "/cgi-bin/echo_headers.py"); // req << header("X-Cpp-Netlib", "rocks!"); // // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.post(req, std::string())); // // std::map headers = parse_headers(body(r)); // BOOST_CHECK_EQUAL(headers["x-cpp-netlib"], "rocks!"); //} cpp-netlib-0.11.2-final/libs/network/test/http/client_types.hpp000066400000000000000000000025741256751517300245360ustar00rootroot00000000000000#ifndef CLIENT_TYPES_ROOWQCLE #define CLIENT_TYPES_ROOWQCLE // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "tag_types.hpp" #include #include #include #include #include #include namespace mpl = boost::mpl; template struct client_adapter { template struct apply { typedef boost::network::http::basic_client type; }; }; typedef mpl::transform >::type client_1_0; typedef mpl::transform >::type client_1_1; typedef mpl::joint_view::type client_types; typedef mpl::joint_view< mpl::transform >::type, client_adapter<1, 0> >::type, mpl::transform >::type, client_adapter<1, 1> >::type>::type async_only_client_types; #endif /* CLIENT_TYPES_ROOWQCLE */ cpp-netlib-0.11.2-final/libs/network/test/http/http_test_server.hpp000066400000000000000000000104431256751517300254320ustar00rootroot00000000000000// // Copyright Kim Grasman 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Changes by Allister Levi Sanchez 2008 // Changes by Dean Michael Berris 2010 #ifndef __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ #define __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ #define BOOST_FILESYSTEM_VERSION 3 #include #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(MIN) #include // ShellExecuteEx #include #pragma comment(lib, "shell32") #else #include // fork, execlp etc. #include #include // for waitpid #include // for chmod #include // for kill #endif struct http_test_server { bool start() { using namespace boost::filesystem; path script_path = get_server_path(current_path()); if (script_path.empty()) return false; path cgibin_path = script_path.parent_path() / "cgi-bin"; if (!set_cgibin_permissions(cgibin_path)) return false; server_child = launch_python_script(script_path); if (server_child == 0) return false; return true; } bool stop() { kill_script(server_child); return true; } private: #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) typedef HANDLE script_handle_t; #else typedef pid_t script_handle_t; #endif boost::filesystem::path get_server_path( const boost::filesystem::path& base_path) { using namespace boost::filesystem; const path script_name = #if defined(HTTPS_SERVER_TEST) "https_test_server.py" #else "http_test_server.py" #endif ; // if executed from $CPP_NETLIB_HOME path server_path = base_path / "libs/network/test/server" / script_name; if (exists(server_path)) return server_path; // if executed from $CPP_NETLIB_HOME/libs/network/test server_path = base_path / "server" / script_name; if (exists(server_path)) return server_path; // if executed from $CPP_NETLIB_HOME/libs/network/test/* server_path = base_path / "../server" / script_name; if (exists(server_path)) return server_path; return path(); } script_handle_t launch_python_script( const boost::filesystem::path& python_script_path) { using namespace boost::filesystem; path::string_type script_name = python_script_path.filename().native(); path::string_type script_dir = python_script_path.parent_path().native(); #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) SHELLEXECUTEINFOA sei = {0}; sei.cbSize = sizeof(sei); sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; sei.lpVerb = "open"; sei.lpFile = "python.exe"; sei.lpParameters = reinterpret_cast(script_name.c_str()); sei.lpDirectory = reinterpret_cast(script_dir.c_str()); sei.nShow = SW_SHOWNOACTIVATE; if (!ShellExecuteExA(&sei)) return 0; return sei.hProcess; #else // Try general Unix code pid_t child_process = fork(); if (child_process < 0) return false; if (child_process == 0) { // child process // cd into script dir and launch python script current_path(script_dir); if (execlp("python", "python", script_name.c_str(), (char*)NULL) == -1) return 0; } else { // parent sleep(1); } return child_process; #endif } void kill_script(script_handle_t h) { #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) TerminateProcess(h, 0U); CloseHandle(h); #else kill(h, SIGTERM); #endif } bool set_cgibin_permissions(const boost::filesystem::path& cgibin_path) { using namespace boost::filesystem; #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) // set the CGI script execute permission for (directory_iterator i(cgibin_path); i != directory_iterator(); ++i) { if (is_regular_file(i->status())) { path::string_type file_path = i->path().string(); if (chmod(file_path.c_str(), S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH | S_IRUSR | S_IRGRP | S_IROTH) != 0) return false; } } #endif return true; } script_handle_t server_child; }; #endif // __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ cpp-netlib-0.11.2-final/libs/network/test/http/message_async_ready_test.cpp000066400000000000000000000010471256751517300270650ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Async Response Test #include #include namespace http = boost::network::http; BOOST_AUTO_TEST_CASE(unready_state_response) { typedef http::basic_response response; response r; BOOST_CHECK(!ready(r)); } cpp-netlib-0.11.2-final/libs/network/test/http/message_test.cpp000066400000000000000000000170141256751517300245050ustar00rootroot00000000000000 // Copyright 2010 (c) Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP message test #include #include #include #include #include #include using namespace boost::network; typedef boost::mpl::list tag_types; struct fixtures {}; BOOST_FIXTURE_TEST_SUITE(http_message_test_suite, fixtures) BOOST_AUTO_TEST_CASE_TEMPLATE(request_constructor_test, T, tag_types) { http::basic_request request("http://boost.org"); typedef typename http::basic_request::string_type string_type; string_type host = http::host(request); boost::uint16_t port = http::port(request); string_type path = http::path(request); string_type query = http::query(request); string_type anchor = http::anchor(request); string_type protocol = http::protocol(request); BOOST_CHECK_EQUAL(host, "boost.org"); BOOST_CHECK_EQUAL(port, 80u); BOOST_CHECK_EQUAL(path, "/"); BOOST_CHECK_EQUAL(query, ""); BOOST_CHECK_EQUAL(anchor, ""); BOOST_CHECK_EQUAL(protocol, "http"); } BOOST_AUTO_TEST_CASE_TEMPLATE(request_copy_constructor_test, T, tag_types) { http::basic_request request("http://boost.org/handler.php"); request << header("Content-Type", "text/plain") << body("Hello, World!"); http::basic_request copy(request); typedef typename http::basic_request::string_type string_type; string_type orig_host = http::host(request), copy_host = http::host(copy); boost::uint16_t orig_port = http::port(request), copy_port = http::port(copy); string_type orig_path = http::path(request), copy_path = http::path(copy); string_type orig_body = body(request), copy_body = body(copy); BOOST_CHECK_EQUAL(orig_host, copy_host); BOOST_CHECK_EQUAL(orig_port, copy_port); BOOST_CHECK_EQUAL(orig_path, copy_path); BOOST_CHECK_EQUAL(orig_body, copy_body); } BOOST_AUTO_TEST_CASE_TEMPLATE(request_assignment_test, T, tag_types) { http::basic_request request("http://boost.org/handler.php"); request << header("Content-Type", "text/plain") << body("Hello, World!"); http::basic_request copy; copy = request; typedef typename http::basic_request::string_type string_type; string_type orig_host = http::host(request), copy_host = http::host(copy); boost::uint16_t orig_port = http::port(request), copy_port = http::port(copy); string_type orig_path = http::path(request), copy_path = http::path(copy); string_type orig_body = body(request), copy_body = body(copy); BOOST_CHECK_EQUAL(orig_host, copy_host); BOOST_CHECK_EQUAL(orig_port, copy_port); BOOST_CHECK_EQUAL(orig_path, copy_path); BOOST_CHECK_EQUAL(orig_body, copy_body); } BOOST_AUTO_TEST_CASE_TEMPLATE(request_swap_test, T, tag_types) { boost::network::http::basic_request request("http://boost.org/"); boost::network::http::basic_request other; swap(other, request); // ADL typedef typename http::basic_request::string_type string_type; string_type orig_host = http::host(request), orig_path = http::path(request), copy_host = http::host(other), copy_path = http::path(other); boost::uint16_t orig_port = http::port(request), copy_port = http::port(request); BOOST_CHECK_EQUAL(orig_host, ""); BOOST_CHECK_EQUAL(orig_port, 80u); BOOST_CHECK_EQUAL(orig_path, "/"); BOOST_CHECK_EQUAL(copy_host, "boost.org"); BOOST_CHECK_EQUAL(copy_port, 80u); BOOST_CHECK_EQUAL(copy_path, "/"); } BOOST_AUTO_TEST_CASE_TEMPLATE(request_uri_directive_test, T, tag_types) { http::basic_request request; request << http::uri("http://boost.org/"); typename http::basic_request::string_type uri_ = http::uri(request); BOOST_CHECK_EQUAL(uri_, "http://boost.org/"); } BOOST_AUTO_TEST_CASE_TEMPLATE(response_constructor_test, T, tag_types) { http::basic_response response; typename http::basic_response::string_type body_ = body(response); BOOST_CHECK_EQUAL(body_, std::string()); } BOOST_AUTO_TEST_CASE_TEMPLATE(response_copy_construct_test, T, tag_types) { using namespace http; http::basic_response response; response << http::version("HTTP/1.1") << http::status(200u) << body("The quick brown fox jumps over the lazy dog") << http::status_message("OK"); http::basic_response copy(response); typename http::basic_response::string_type version_orig = version(response), version_copy = version(copy); BOOST_CHECK_EQUAL(version_orig, version_copy); boost::uint16_t status_orig = status(response), status_copy = status(copy); BOOST_CHECK_EQUAL(status_orig, status_copy); typename http::basic_response::string_type status_message_orig = status_message(response), status_message_copy = status_message(copy), body_orig = body(response), body_copy = body(copy); BOOST_CHECK_EQUAL(status_message_orig, status_message_copy); BOOST_CHECK_EQUAL(body_orig, body_copy); } BOOST_AUTO_TEST_CASE_TEMPLATE(response_assignment_construct_test, T, tag_types) { http::basic_response response; response << http::version("HTTP/1.1") << http::status(200) << http::status_message("OK") << body("The quick brown fox jumps over the lazy dog"); http::basic_response copy; copy = response; typedef typename http::basic_response::string_type string_type; string_type version_orig = version(response), version_copy = version(copy); BOOST_CHECK_EQUAL(version_orig, version_copy); boost::uint16_t status_orig = status(response), status_copy = status(copy); BOOST_CHECK_EQUAL(status_orig, status_copy); string_type status_message_orig = status_message(response), status_message_copy = status_message(copy); BOOST_CHECK_EQUAL(status_message_orig, status_message_copy); string_type body_orig = body(response), body_copy = body(copy); BOOST_CHECK_EQUAL(body_orig, body_copy); } BOOST_AUTO_TEST_CASE_TEMPLATE(response_swap_test, T, tag_types) { using namespace boost::network::http; http::basic_response response; response << version("HTTP/1.1") << status(200) << status_message("OK") << body("RESPONSE"); boost::network::http::basic_response swapped; BOOST_REQUIRE_NO_THROW(swap(response, swapped)); BOOST_CHECK_EQUAL(response.version(), std::string()); BOOST_CHECK_EQUAL(response.status(), 0u); BOOST_CHECK_EQUAL(response.status_message(), std::string()); typename http::basic_response::string_type orig_body = body(response), swapped_body = body(swapped); BOOST_CHECK_EQUAL(orig_body, std::string()); BOOST_CHECK_EQUAL(swapped.version(), std::string("HTTP/1.1")); BOOST_CHECK_EQUAL(swapped.status(), 200u); BOOST_CHECK_EQUAL(swapped.status_message(), std::string("OK")); BOOST_CHECK_EQUAL(swapped_body, std::string("RESPONSE")); } BOOST_AUTO_TEST_SUITE_END() cpp-netlib-0.11.2-final/libs/network/test/http/request_incremental_parser_test.cpp000066400000000000000000000132151256751517300305050ustar00rootroot00000000000000// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Incremental Request Parser Test #include #include #include #include #include #include #include #include /** Synopsis * * Test for the HTTP Request Incremental Parser * -------------------------------------------- * * In this test we fully intend to specify how an incremental HTTP request * parser should be used. This follows the HTTP Response Incremental Parser * example, and models the Incremental Parser Concept. * */ namespace tags = boost::network::tags; namespace logic = boost::logic; namespace fusion = boost::fusion; using namespace boost::network::http; BOOST_AUTO_TEST_CASE(incremental_parser_constructor) { request_parser p; // default constructible } BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_method) { request_parser p; logic::tribool parsed_ok = false; typedef request_parser request_parser_type; typedef boost::iterator_range range_type; range_type result_range; std::string valid_http_method = "GET "; fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::method_done, valid_http_method); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); std::string parsed(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; std::string invalid_http_method = "get "; p.reset(); fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::method_done, invalid_http_method); BOOST_CHECK_EQUAL(parsed_ok, false); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; } BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_uri) { request_parser p; logic::tribool parsed_ok = false; typedef request_parser request_parser_type; typedef boost::iterator_range range_type; range_type result_range; std::string valid_http_request = "GET / HTTP/1.1\r\n"; fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::uri_done, valid_http_request); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); std::string parsed(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; std::string invalid_http_request = "GET /\t HTTP/1.1\r\n"; p.reset(); fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::uri_done, invalid_http_request); BOOST_CHECK_EQUAL(parsed_ok, false); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; } BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) { request_parser p; logic::tribool parsed_ok = false; typedef request_parser request_parser_type; typedef boost::iterator_range range_type; range_type result_range; std::string valid_http_request = "GET / HTTP/1.1\r\n"; fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::version_done, valid_http_request); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); std::string parsed(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; std::string invalid_http_request = "GET / HTTP 1.1\r\n"; p.reset(); fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::version_done, invalid_http_request); BOOST_CHECK_EQUAL(parsed_ok, false); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; } BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_headers) { request_parser p; logic::tribool parsed_ok = false; typedef request_parser request_parser_type; typedef boost::iterator_range range_type; range_type result_range; std::string valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\n\r\n"; fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::headers_done, valid_http_request); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); std::string parsed(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\nConnection: close\r\n\r\n"; p.reset(); fusion::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::headers_done, valid_http_request); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; } cpp-netlib-0.11.2-final/libs/network/test/http/request_linearize_test.cpp000066400000000000000000000052011256751517300266060ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Request Linearize Test #include #include #include #include #include #include namespace http = boost::network::http; namespace tags = boost::network::http::tags; namespace mpl = boost::mpl; namespace net = boost::network; typedef mpl::list tag_types; BOOST_AUTO_TEST_CASE_TEMPLATE(linearize_request, T, tag_types) { http::basic_request request("http://www.boost.org"); static char http_1_0_output[] = "GET / HTTP/1.0\r\n" "Host: www.boost.org\r\n" "Accept: */*\r\n" "Connection: Close\r\n" "\r\n"; static char http_1_1_output[] = "GET / HTTP/1.1\r\n" "Host: www.boost.org\r\n" "Accept: */*\r\n" "Accept-Encoding: identity;q=1.0, *;q=0\r\n" "Connection: Close\r\n" "\r\n"; typename http::basic_request::string_type output_1_0; linearize(request, "GET", 1, 0, std::back_inserter(output_1_0)); BOOST_CHECK_EQUAL(output_1_0, http_1_0_output); typename http::basic_request::string_type output_1_1; linearize(request, "GET", 1, 1, std::back_inserter(output_1_1)); BOOST_CHECK_EQUAL(output_1_1, http_1_1_output); } BOOST_AUTO_TEST_CASE_TEMPLATE(linearize_request_override_headers, T, tag_types) { http::basic_request request("http://www.boost.org"); // We can override the defaulted headers and test that here. request << net::header("Accept", ""); static char http_1_0_no_accept_output[] = "GET / HTTP/1.0\r\n" "Host: www.boost.org\r\n" "Connection: Close\r\n" "\r\n"; static char http_1_1_no_accept_output[] = "GET / HTTP/1.1\r\n" "Host: www.boost.org\r\n" "Accept-Encoding: identity;q=1.0, *;q=0\r\n" "Connection: Close\r\n" "\r\n"; typename http::basic_request::string_type output_1_0; linearize(request, "GET", 1, 0, std::back_inserter(output_1_0)); BOOST_CHECK_EQUAL(output_1_0, http_1_0_no_accept_output); typename http::basic_request::string_type output_1_1; linearize(request, "GET", 1, 1, std::back_inserter(output_1_1)); BOOST_CHECK_EQUAL(output_1_1, http_1_1_no_accept_output); } cpp-netlib-0.11.2-final/libs/network/test/http/response_incremental_parser_test.cpp000066400000000000000000000422161256751517300306560ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2010. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Incremental Parser Test #include #include #include #include #include #include #include /** Synopsis * * Test for HTTP Response Incremental Parser * ----------------------------------------- * * In this test we fully intend to specify how an incremental * HTTP Response parser should be used. This defines the bare * minimum implementation for an Incremental Parser concept, * and shall follow an interface that puts a premium on simplicity. * * The motivation for coming up with a re-startable stateful * incremental parser comes from the requirement in the asynchronous * HTTP client implementation that allows for parsing an HTTP * response as the data comes in. By being able to process some * parts of the message ahead of others, we are allowed to set * the promise values bound to futures that the users of the client * would be waiting on. * * The basic interface that we're looking for is a means of providing: * - a range of input * - a means of resetting the parser's state * - a means of initializing the parser to a given state * - a parse_until function that takes a state as parameter and * a range from which the parser will operate on, returns * a tuple of a boost::logic::tribool and a resulting range * * One of the possible implementations can use the Boost.MSM library * to create the state machine. The test however does not specify what * implementation should be used, but rather that the interface and the * semantics are according to expectations. * * Date: September 9, 2010 * Author: Dean Michael Berris */ namespace tags = boost::network::tags; namespace logic = boost::logic; namespace fusion = boost::fusion; using namespace boost::network::http; struct crlf { static const std::string literal; }; const std::string crlf::literal = "\r\n"; struct lf { static const std::string literal; }; const std::string lf::literal = "\n"; typedef boost::mpl::vector eol_types; BOOST_AUTO_TEST_CASE(incremental_parser_constructor) { response_parser p; // default constructible } /** In this test we want to be able to parse incrementally a * range passed in as input, and specify to the parser that * it should stop when we reach a certain state. In this case * we want it to parse until it either finds the HTTP version * or there is an error encountered. */ BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) { response_parser p; // default constructible logic::tribool parsed_ok = false; typedef response_parser response_parser_type; typedef boost::iterator_range range_type; range_type result_range; std::string valid_http_version = "HTTP/1.0 "; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); std::string parsed(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(); valid_http_version = "HTTP/1.1 "; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(!boost::empty(result_range)); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(); std::string invalid_http_version = "HTTP 1.0"; parsed_ok = logic::indeterminate; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, invalid_http_version); BOOST_CHECK_EQUAL(parsed_ok, false); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(); valid_http_version = "HTTP/0.9 "; parsed_ok = logic::indeterminate; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); BOOST_CHECK_EQUAL(parsed_ok, true); parsed.assign(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } /** In this test we then want to check that we can parse a status * string right after the version string. We should expect that * the parser doesn't do any conversions from string to integer * and outsource that part to the user of the parser. */ BOOST_AUTO_TEST_CASE_TEMPLATE(incremental_parser_parse_status, eol, eol_types) { typedef response_parser response_parser_type; typedef boost::iterator_range range_type; // We want to create a parser that has been initialized to a specific // state. In this case we assume that the parser has already parsed // the version part of the HTTP Response. response_parser_type p(response_parser_type::http_version_done); std::string valid_status = "200 "; logic::tribool parsed_ok; range_type result_range; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_status_done, valid_status); BOOST_CHECK_EQUAL(parsed_ok, true); std::string parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_version_done); std::string invalid_status = "200x "; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_status_done, invalid_status); BOOST_CHECK_EQUAL(parsed_ok, false); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; valid_status = "200" + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_status_done, valid_status); BOOST_CHECK_EQUAL(parsed_ok, true); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } /** In this test then we get the rest of the first line of the HTTP * Response, and treat it as the status message. */ BOOST_AUTO_TEST_CASE_TEMPLATE(incremental_parser_parse_status_message, eol, eol_types) { typedef response_parser response_parser_type; typedef boost::iterator_range range_type; response_parser_type p(response_parser_type::http_status_done); std::string valid_status_message = "OK" + eol::literal + "Server: Foo"; logic::tribool parsed_ok; range_type result_range; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); BOOST_CHECK_EQUAL(parsed_ok, true); std::string parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_done); valid_status_message = "OK" + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); BOOST_CHECK_EQUAL(parsed_ok, true); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_done); valid_status_message = "Internal Server Error" + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); BOOST_CHECK_EQUAL(parsed_ok, true); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_done); valid_status_message = eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); BOOST_CHECK_EQUAL(parsed_ok, true); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_done); valid_status_message = "한글메시지" + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); BOOST_CHECK_EQUAL(parsed_ok, true); parsed = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } /** This test specifices how one-line-per-header parsing happens incrementally. */ BOOST_AUTO_TEST_CASE_TEMPLATE(incremental_parser_parse_header_lines, eol, eol_types) { typedef response_parser response_parser_type; typedef boost::iterator_range range_type; response_parser_type p(response_parser_type::http_status_message_done); std::string valid_headers = "Server: Foo" + eol::literal + "Content-Type: application/json" + eol::literal + eol::literal; logic::tribool parsed_ok; range_type result_range; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); std::string parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); std::string::const_iterator end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); std::string parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); p.reset(response_parser_type::http_status_message_done); valid_headers = " Server: Foo" + eol::literal + " Content-Type: application/json" + eol::literal + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); p.reset(response_parser_type::http_status_message_done); valid_headers = "_Server: Foo" + eol::literal + "_Content-Type: application/json" + eol::literal + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); p.reset(response_parser_type::http_status_message_done); valid_headers = "Server: " + eol::literal + "Content-Type: application/json" + eol::literal + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); p.reset(response_parser_type::http_status_message_done); valid_headers = "Server: 서버" + eol::literal + "Content-Type: application/json" + eol::literal + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); p.reset(response_parser_type::http_status_message_done); valid_headers = "Content-Type: text/html;" + eol::literal + "charset=utf-8" + eol::literal + eol::literal; fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); end = valid_headers.end(); valid_headers.assign(boost::end(result_range), end); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(boost::end(result_range), end); p.reset(response_parser_type::http_status_message_done); fusion::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); BOOST_CHECK_EQUAL(parsed_ok, true); BOOST_CHECK(parsed1 != parsed2); } cpp-netlib-0.11.2-final/libs/network/test/http/server_async.cpp000066400000000000000000000033611256751517300245250ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests #include #include #include #include namespace net = boost::network; namespace http = boost::network::http; namespace utils = boost::network::utils; struct async_hello_world; typedef http::async_server server; struct async_hello_world { struct is_content_length { template bool operator()(Header const& header) { return boost::iequals(name(header), "content-length"); } }; void operator()(server::request const& request, server::connection_ptr connection) { static server::response_header headers[] = {{"Connection", "close"}, {"Content-Type", "text/plain"}, {"Server", "cpp-netlib/0.9"}, {"Content-Length", "13"}}; static std::string hello_world("Hello, World!"); connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers + 4)); connection->write(hello_world); } }; int main(int argc, char* argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; server instance("localhost", port, handler, thread_pool, http::_reuse_address = true); instance.run(); return 0; } cpp-netlib-0.11.2-final/libs/network/test/http/server_async_less_copy.cpp000066400000000000000000000040111256751517300265760ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests #include #include #include #include #include #include namespace net = boost::network; namespace http = boost::network::http; namespace utils = boost::network::utils; struct async_hello_world; typedef http::async_server server; struct async_hello_world { struct is_content_length { template bool operator()(Header const& header) { return boost::iequals(name(header), "content-length"); } }; void operator()(server::request const& request, server::connection_ptr connection) { static server::response_header headers[] = {{"Connection", "close"}, {"Content-Type", "text/plain"}, {"Server", "cpp-netlib/0.9"}, {"Content-Length", "13"}}; static char const* hello_world = "Hello, World!"; connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers + 4)); std::vector iovec; iovec.push_back(boost::asio::const_buffer(hello_world, 13)); connection->write(iovec, boost::bind(&async_hello_world::error, this, _1)); } void error(boost::system::error_code const& ec) { // do nothing here. } }; int main(int argc, char* argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address = true); instance.run(); return 0; } cpp-netlib-0.11.2-final/libs/network/test/http/server_async_run_stop_concurrency.cpp000066400000000000000000000114221256751517300310650ustar00rootroot00000000000000#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests #ifdef BOOST_TEST_DYN_LINK #define BOOST_TEST_NO_MAIN #endif /* BOOST_TEST_DYN_LINK */ #include #include #include namespace http = boost::network::http; namespace util = boost::network::utils; struct dummy_async_handler; typedef http::async_server async_server; struct dummy_async_handler { void operator()(async_server::request const& req, async_server::connection_ptr conn) { // Really, this is just for testing purposes } }; // In this batch of tests we ensure that calling run and stop on an // async_server, in any sequence, is thread safe. int main(int argc, char* argv[]) { dummy_async_handler async_handler; #define ASYNC_SERVER_TEST_CONFIG \ options.address("127.0.0.1").port("8007").reuse_address(true) #define ASYNC_SERVER_SLEEP_TIME boost::posix_time::milliseconds(100) // stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop without running"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); } // run-stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); server_instance.stop(); running_thread.join(); } // run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); } // run-stop-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_stopping_thread.join(); second_running_thread.join(); } // run-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_running_thread.join(); } // run-stop-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread( boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread( boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); second_stopping_thread.join(); running_thread.join(); } #undef ASYNC_SERVER_TEST_CONFIG return 0; } #ifdef BOOST_TEST_DYN_LINK #undef BOOST_TEST_NO_MAIN #endif /* BOOST_TEST_DYN_LINK */ cpp-netlib-0.11.2-final/libs/network/test/http/server_constructor_test.cpp000066400000000000000000000061751256751517300270420ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Server Construtor Tests #include #include namespace http = boost::network::http; namespace util = boost::network::utils; struct dummy_sync_handler; struct dummy_async_handler; typedef http::server sync_server; typedef http::async_server async_server; struct dummy_sync_handler { void operator()(sync_server::request const &req, sync_server::response &res) { // Really, this is just for testing purposes } void log(char const *) {} }; struct dummy_async_handler { void operator()(async_server::request const &req, async_server::connection_ptr conn) { // Really, this is just for testing purposes } }; BOOST_AUTO_TEST_CASE(minimal_constructor) { dummy_sync_handler sync_handler; dummy_async_handler async_handler; sync_server::options sync_options(sync_handler); async_server::options async_options(async_handler); BOOST_CHECK_NO_THROW( sync_server sync_instance(sync_options.address("127.0.0.1").port("80"))); BOOST_CHECK_NO_THROW(async_server async_instance( async_options.address("127.0.0.1").port("80"))); } BOOST_AUTO_TEST_CASE(with_io_service_parameter) { dummy_sync_handler sync_handler; dummy_async_handler async_handler; boost::shared_ptr thread_pool; boost::shared_ptr io_service; sync_server::options sync_options(sync_handler); async_server::options async_options(async_handler); BOOST_CHECK_NO_THROW( sync_server sync_instance(sync_options.address("127.0.0.1") .port("80") .io_service(io_service) .thread_pool(thread_pool))); BOOST_CHECK_NO_THROW( async_server async_instance(async_options.address("127.0.0.1") .port("80") .io_service(io_service) .thread_pool(thread_pool))); } BOOST_AUTO_TEST_CASE(throws_on_failure) { dummy_sync_handler sync_handler; dummy_async_handler async_handler; boost::shared_ptr thread_pool; boost::shared_ptr io_service; sync_server::options sync_options(sync_handler); async_server::options async_options(async_handler); sync_server sync_instance(sync_options.address("127.0.0.1") .port("80") .io_service(io_service) .thread_pool(thread_pool)); async_server async_instance(async_options.address("127.0.0.1") .port("80") .io_service(io_service) .thread_pool(thread_pool)); BOOST_CHECK_THROW(sync_instance.run(), std::runtime_error); BOOST_CHECK_THROW(async_instance.run(), std::runtime_error); } cpp-netlib-0.11.2-final/libs/network/test/http/server_header_parser_test.cpp000066400000000000000000000036661256751517300272630ustar00rootroot00000000000000// Copyright 2013 Rudolfs Bundulis // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Server Header Parser Test #include #include #include #define BOOST_LOCALE_NO_LIB #include #include #include /** Synopsis * * Test for Utf8 support in the asynchronous connection header parser * -------------------------------------------- * * This test checks for Utf8 support in the header parser * for asynchronous connection * */ namespace tags = boost::network::tags; namespace logic = boost::logic; namespace fusion = boost::fusion; using namespace boost::network::http; BOOST_AUTO_TEST_CASE(async_connection_parse_headers) { std::wstring utf16_test_name = L"R\u016bdolfs"; request_header_narrow utf8_header = { "X-Utf8-Test-Header", boost::locale::conv::utf_to_utf(utf16_test_name)}; std::string valid_http_request; valid_http_request.append(utf8_header.name) .append(": ") .append(utf8_header.value) .append("\r\n\r\n"); std::vector headers; parse_headers(valid_http_request, headers); std::vector::iterator header_iterator = headers.begin(); for (; header_iterator != headers.end(); ++header_iterator) { if (header_iterator->name == utf8_header.name && header_iterator->value == utf8_header.value) break; } std::wstring utf16_test_name_from_header = boost::locale::conv::utf_to_utf(header_iterator->value); BOOST_CHECK(header_iterator != headers.end()); BOOST_CHECK(utf16_test_name_from_header == utf16_test_name); std::cout << "utf8 header parsed, name: " << header_iterator->name << ", value: " << header_iterator->value; } cpp-netlib-0.11.2-final/libs/network/test/http/server_hello_world.cpp000066400000000000000000000027041256751517300257220ustar00rootroot00000000000000// Copyright 2009 (c) Tarro, Inc. // Copyright 2009-2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include #include #include namespace http = boost::network::http; using boost::assign::list_of; using boost::lexical_cast; using std::string; using std::cerr; using std::endl; struct hello_world; typedef http::server server; struct hello_world { void operator()(server::request const& request, server::response& response) { static server::response::header_type header = {"Connection", "close"}; response = server::response::stock_reply(server::response::ok, "Hello, World!"); response.headers.push_back(header); assert(response.status == server::response::ok); assert(response.headers.size() == 3); assert(response.content == "Hello, World!"); } void log(string const& data) { cerr << data << endl; abort(); } }; int main(int argc, char* argv[]) { hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; server server_("127.0.0.1", port, handler, http::_reuse_address = true); server_.run(); return EXIT_SUCCESS; } cpp-netlib-0.11.2-final/libs/network/test/http/server_include_inlined.cpp000066400000000000000000000032231256751517300265320ustar00rootroot00000000000000// Copyright 2009 (c) Tarro, Inc. // Copyright 2009-2010 (c) Dean Michael Berris // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #include #include #define BOOST_NETWORK_NO_LIB #include #include #include #include #include #include namespace http = boost::network::http; using boost::assign::list_of; using boost::lexical_cast; using std::string; using std::cerr; using std::endl; struct hello_world; typedef http::server server; struct hello_world { void operator()(server::request const& request, server::response& response) { static server::response::header_type header = {"Connection", "close"}; response = server::response::stock_reply(server::response::ok, "Hello, World!"); response.headers.push_back(header); assert(response.status == server::response::ok); assert(response.headers.size() == 3); assert(response.content == "Hello, World!"); } void log(string const& data) { cerr << data << endl; abort(); } }; int main(int argc, char* argv[]) { hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; server server_("127.0.0.1", port, handler, http::_reuse_address = true); boost::thread runner(boost::bind(&server::run, &server_)); try { server_.stop(); runner.join(); } catch (...) { /* ignore all errors */ } return EXIT_SUCCESS; } cpp-netlib-0.11.2-final/libs/network/test/http/tag_types.hpp000066400000000000000000000015041256751517300240230ustar00rootroot00000000000000#ifndef TAG_TYPES_4NNM8B5T #define TAG_TYPES_4NNM8B5T // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include namespace http = boost::network::http; typedef boost::mpl::vector tag_types; #endif /* TAG_TYPES_4NNM8B5T */ cpp-netlib-0.11.2-final/libs/network/test/http_server_async_less_copy.cpp000066400000000000000000000047711256751517300266730ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests #include #include #include #include #include namespace net = boost::network; namespace http = boost::network::http; namespace utils = boost::network::utils; struct async_hello_world; typedef http::async_server server; struct async_hello_world { struct is_content_length { template bool operator()(Header const& header) { return boost::iequals(header.name, "content-length"); } }; void operator()(server::request const& request, server::connection_ptr connection) { static server::response_header headers[] = { {"Connection", "close"}, {"Content-Type", "text/plain"}, {"Server", "cpp-netlib/0.9-devel"}}; if (request.method == "HEAD") { connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers + 3)); } else { if (request.method == "PUT" || request.method == "POST") { static std::string bad_request("Bad Request."); server::request::headers_container_type::iterator found = boost::find_if(request.headers, is_content_length()); if (found == request.headers.end()) { connection->set_status(server::connection::bad_request); connection->set_headers( boost::make_iterator_range(headers, headers + 3)); connection->write(bad_request); return; } } static char const* hello_world = "Hello, World!"; connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers + 3)); std::vector iovec; iovec.push_back(boost::asio::const_buffer(hello_world, 13)); connection->write(iovec, boost::bind(&async_hello_world::error, this, _1)); } } void error(boost::system::error_code const& ec) { // do nothing here. } }; int main(int argc, char* argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; server instance("127.0.0.1", "8000", handler, thread_pool); instance.run(); return 0; } cpp-netlib-0.11.2-final/libs/network/test/httplib_acceptance.py000066400000000000000000000052661256751517300245330ustar00rootroot00000000000000# Copyright (c) 2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) #!/bin/env python from sys import argv from time import sleep import httplib2 as httplib from subprocess import Popen,PIPE if len(argv) < 4: print('I need the executable to run, the port to run it on, and the final touched file indicator.') exit(1) print('Running {0} on port {1}...'.format(argv[1], argv[2])) pipe = None try: pipe = Popen(args=[argv[1], argv[2]], executable=argv[1], stdin=PIPE, stdout=PIPE, close_fds=True) print('Done with spawning {0}.'.format(argv[1])) print('Sleeping to give the server a chance to run...') sleep(1) except: print('I cannot spawn \'{0}\' properly.'.format(argv[1])) exit(1) status = 0 client = httplib.Http(timeout=5) expected = b'Hello, World!' def test(url, method, expected, headers={}, body=''): global status try: print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), resp, content = client.request(url, method, headers=headers, body=body) if content != expected: print('ERROR: \'{0}\' != \'{1}\'; sizes: {2} != {3}'.format(content, expected, len(content), len(expected))) status = 1 else: print('... passed.') except Exception as e: print('Caught Exception: {0}'.format(e)) status = 1 def test_status(url, method, expected, headers={}, body=''): global status try: print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), resp, content = client.request('http://localhost:8000/', 'PUT', body='') if resp['status'] != expected: print('ERROR: response status (got {0}) != expecting {1}'.format(resp['status'], expected)) status = 1 else: print('... passed.') except Exception as e: print('Caught Exception: {0}'.format(e)) status = 1 url = 'http://127.0.0.1:{0}/'.format(argv[2]) test(url, 'GET', expected) test(url, 'DELETE', expected) # Good request case, there's a content-length header for POST test(url, 'POST', expected, {'Content-Length': '0'}) # Good request case, there's a content-length header for PUT test(url, 'PUT', expected, {'Content-Length': '0'}) # Bad request case, no content-length for POST test_status(url, 'POST', '400') # Bad request case, no content-length for PUT test_status(url, 'PUT', '400') if status != 0: print('Failures encountered.') pipe.terminate() exit(status) open(argv[len(argv) - 1], 'w').close() print('All tests pass.') pipe.terminate() cpp-netlib-0.11.2-final/libs/network/test/message_test.cpp000066400000000000000000000125001256751517300235210ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE message test #include #include #include #include #include using namespace boost::network; typedef boost::mpl::list tag_types; struct string_header_name { static std::string string; }; std::string string_header_name::string = "Header"; struct wstring_header_name { static std::wstring string; }; std::wstring wstring_header_name::string = L"Header"; struct string_header_value { static std::string string; }; std::string string_header_value::string = "Value"; struct wstring_header_value { static std::wstring string; }; std::wstring wstring_header_value::string = L"Value"; template struct header_name : string_header_name {}; template <> struct header_name : wstring_header_name {}; template struct header_value : string_header_value {}; template <> struct header_value : wstring_header_value {}; struct string_body_data { static std::string string; }; std::string string_body_data::string = "The quick brown fox jumps over the lazy dog."; struct wstring_body_data { static std::wstring string; }; std::wstring wstring_body_data::string = L"The quick brown fox jumps over the lazy dog."; template struct body_data : string_body_data {}; template <> struct body_data : wstring_body_data {}; struct string_source_data { static std::string string; }; std::string string_source_data::string = "Source"; struct wstring_source_data { static std::wstring string; }; std::wstring wstring_source_data::string = L"Source"; template struct source_data : string_source_data {}; template <> struct source_data : wstring_body_data {}; struct string_destination_data { static std::string string; }; std::string string_destination_data::string = "Destination"; struct wstring_destination_data { static std::wstring string; }; std::wstring wstring_destination_data::string = L"Destination"; template struct destination_data : string_destination_data {}; template <> struct destination_data : wstring_destination_data {}; /** * Defines a set of template functions that can be used to test * generic code. */ BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { basic_message instance; instance << header(header_name::string, header_value::string); basic_message copy(instance); BOOST_CHECK_EQUAL(headers(copy).count(header_name::string), static_cast(1)); typename headers_range >::type range = headers(copy)[header_name::string]; BOOST_CHECK(boost::begin(range) != boost::end(range)); } BOOST_AUTO_TEST_CASE_TEMPLATE(swap_test, T, tag_types) { basic_message instance; instance << header(header_name::string, header_value::string); basic_message other; swap(instance, other); BOOST_CHECK_EQUAL(headers(instance).count(header_name::string), static_cast(0)); BOOST_CHECK_EQUAL(headers(other).count(header_name::string), static_cast(1)); } BOOST_AUTO_TEST_CASE_TEMPLATE(headers_directive_test, T, tag_types) { basic_message instance; instance << header(header_name::string, header_value::string); BOOST_CHECK_EQUAL(headers(instance).count(header_name::string), static_cast(1)); typename headers_range >::type range = headers(instance)[header_name::string]; BOOST_CHECK(boost::begin(range) != boost::end(range)); } BOOST_AUTO_TEST_CASE_TEMPLATE(body_directive_test, T, tag_types) { basic_message instance; instance << ::boost::network::body(body_data::string); typename string::type body_string = body(instance); BOOST_CHECK(body_string == body_data::string); } BOOST_AUTO_TEST_CASE_TEMPLATE(source_directive_test, T, tag_types) { basic_message instance; instance << ::boost::network::source(source_data::string); typename string::type source_string = source(instance); BOOST_CHECK(source_string == source_data::string); } BOOST_AUTO_TEST_CASE_TEMPLATE(destination_directive_test, T, tag_types) { basic_message instance; instance << destination(destination_data::string); BOOST_CHECK(destination(instance) == destination_data::string); } BOOST_AUTO_TEST_CASE_TEMPLATE(remove_header_directive_test, T, tag_types) { basic_message instance; instance << header(header_name::string, header_value::string) << remove_header(header_name::string); typename headers_range >::type range = headers(instance); BOOST_CHECK(boost::begin(range) == boost::end(range)); } cpp-netlib-0.11.2-final/libs/network/test/message_transform_test.cpp000066400000000000000000000023131256751517300256150ustar00rootroot00000000000000 // Copyright Dean Michael Berris 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE message test #include #include #include #include BOOST_AUTO_TEST_CASE(message_transform_toupper) { using namespace boost::network; message msg; msg << source("me"); BOOST_CHECK_EQUAL(source(msg), "me"); msg << transform(to_upper_, source_); BOOST_CHECK_EQUAL(source(msg), "ME"); msg << destination("you"); BOOST_CHECK_EQUAL(destination(msg), "you"); msg << transform(to_upper_, destination_); BOOST_CHECK_EQUAL(destination(msg), "YOU"); } BOOST_AUTO_TEST_CASE(message_transform_tolower) { using namespace boost::network; message msg; msg << source("ME"); BOOST_CHECK_EQUAL(source(msg), "ME"); msg << transform(to_lower_, source_); BOOST_CHECK_EQUAL(source(msg), "me"); msg << destination("YOU"); BOOST_CHECK_EQUAL(destination(msg), "YOU"); msg << transform(to_lower_, destination_); BOOST_CHECK_EQUAL(destination(msg), "you"); } cpp-netlib-0.11.2-final/libs/network/test/server/000077500000000000000000000000001256751517300216425ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/test/server/boost.jpg000066400000000000000000000107061256751517300234760ustar00rootroot00000000000000JFIF``HExifII*1&8Adobe ImageReadyȯC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222V" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ) f{@L N(((((((((((((() 5B{o8?oU9E)(GlFe8 )ؼ+F[0,7x|V#cK=4*:Z ŅXáPͻhzk~"V͎3HFކ"FYMdN;:൯Zm:l |!;#CnOZ|e29?VM3u"aLUMON-goz5gݜ4 S(J;)lX$m$2Rk־)iN5 }2/ƈa%^='ŭhc}p=3iU5=8"̶흿5nUbzu^Re Uc;܂MڡEd[J?uܜYν>o.#:+%g"{{F0I~"zGn(,vyd'>}aH$Ԯs.Wܐ?LWxV^# -јzkI$z^a;]+=5CĠG' 㮊m$i&=~(3()өh) c_m!fOQZsچ@ }ߌNeYF3Kmd%M+OJr9YKU=l) Ѿ_iK`y;vԔ悊MVcZYG9f9&VEt8e9EFGKw]o2ʝ*Қhmbs!ݏAZi^-TGID/8i"@k<ExĐOBWwnfY&iHtcg?w..H`8?1~h{3=3;oi॥TX= #^^[kTKI3JQYҔPOy$~!S[#?Ĥ`DtQ--m-&I}}o{I_j$D!Sس@pzq]L/$}&QN}j G<|HwvM7\A}/L?gیnۿE^ DXFYŎZ $m$Z١v{iPK nd#WUPϿә`A#򬯊:^xm`VXV;Σ0!?yZN̢SC?W%ԟEO=ϵQGⰉzF=Oƥu3;$OE^ DXFYŎZ&,>O ʋn1snOq|5gH ?{xE/7Vc/gYF7Ǧ@O>iCR?m qnf?k?Nws<$0*%JH+V>-]z  OaPK\Ӆ>v IBZE= ^ kJIc`yV ך(IqrGi ^N5Er(( F!PNx6ΫP6O嘳X{צ]BDXa y[ y{pRqbS}WK˷u{Sy}=Erk4؍KoA[bN΄[W"p0\aRp{ӠJ$yTԵu}^Ps;^?,O xi-nqzK|uÀ8+@V:r8I+RB.z8Vb>W+ieW)sw;nwnެǰf<*?]=n%sOt< H<'hPʾ 'q_I1z Oh3:n9 1)9g_@U{ MJ٭m$\Qݗ8)+3/\nMo=őCmh{V֩jIm=3O0i6ߢ] 73Hn!i |5lY~C&bj%kK躟5FZGv4W'^imXv=IigmcnG+#P: 9OaϠH$ QixK>6S[qdPZ2z׶[<'H_c\ 73Hn!kEV.6!Ӓwj٣4 0&m(.QVݷ;$׭Z5ճkig#zq WQigmcnG+#P+Cr<~x1fj֕نN W3 z{i6:՟5|7ٽӕ '+ /&%#(}ʒ9[&7K$+0X IN^ ¿ ɉaitU9Vvi>q8SR%oF?I澻qyj0c3NsVOy[cW7vvmwM 2852=Tx'Sqk'),1qЃ{/|B&Z5O3~8T?<*I'JO(٫oL{%ɷRHMŹ''I8KT&wz(()SYjHtV> ^"ml&(( JKaiR▐-P=n~8" qWr)9ҷ?vQM#3E٤}HAFs.l I @u+J/Xd>oqC.>ml袐̿!ŲLdw plLַ+w#8ıoȌSS&ne.J-Y$a = qR:wf=)f xx(c7BYcPy,@AW议mCnu 9+ukZnZ- Zۭ].Qg$sMiaa ,gfcIǾ(m,R%m"cx1(d0`0rs n-㕣8UVY+n먡JՈ,h,`y#U281Bܵ=UvDP2' 0: name = header[0] if len(header) > 1: value = ': '.join(header[1:]) # re-join the rest of the items as value if len(name) > 0: dict[name] = value return dict cpp-netlib-0.11.2-final/libs/network/test/server/cgi-bin/echo_body.py000077500000000000000000000013011256751517300254550ustar00rootroot00000000000000#!/usr/bin/python # # Copyright Divye Kapoor 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http:#www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI application on localhost # It can be accessed by http://localhost:8000/cgi-bin/echo_form.py # It returns the query parameters passed to the CGI Script as plain text. # import cgitb; cgitb.enable() # for debugging only import cgi import os, sys sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) sys.stdout.write( "\r\n" ) # POST data/form data is available in the .value property sys.stdout.write( cgi.FieldStorage().value ) cpp-netlib-0.11.2-final/libs/network/test/server/cgi-bin/echo_headers.py000077500000000000000000000011521256751517300261370ustar00rootroot00000000000000#!/usr/bin/python # # Copyright Kim Grasman 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http:#www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI application on localhost # It can be accessed by http://localhost:8000/cgi-bin/echo_headers.py # import cgi import os, sys import cgisupport sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) sys.stdout.write( "\r\n" ) hdrs = cgisupport.http_headers(os.environ.get('HTTP_ALL_HEADERS')) for h,v in hdrs.iteritems(): print h + ": " + v cpp-netlib-0.11.2-final/libs/network/test/server/cgi-bin/multiline-header.py000077500000000000000000000024161256751517300267620ustar00rootroot00000000000000#!/usr/bin/python # # Copyright Divye Kapoor 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http:#www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI application on localhost # It can be accessed by http://localhost:8000/cgi-bin/requestinfo.py # It returns the query parameters passed to the CGI Script as plain text. # import cgitb; cgitb.enable() # for debugging only import cgi import os, sys print "X-CppNetlib-Test: multi-line-header\r\n" print " that-should-concatenate\r\n" print "Content-type: text/plain; charset=us-ascii\r\n\r\n" print "\r\n" form = cgi.FieldStorage() qstring = "" qstring_dict = {} if os.environ.has_key("QUERY_STRING"): qstring = os.environ["QUERY_STRING"] try: qstring_dict = cgi.parse_qs(qstring,1,1) # parse_qs(query_string,keep_blanks,strict_parsing) except ValueError: print "Error parsing query string." print "Query string:", qstring print "GET parameters:", for i in qstring_dict.keys(): print i,"-",qstring_dict[i],";", print # Remove GET params and print only the POST ones print "POST parameters:", for i in form.keys(): if i not in qstring_dict.keys(): print i,"-",form.getfirst(i, ""),";", print cpp-netlib-0.11.2-final/libs/network/test/server/cgi-bin/requestinfo.py000077500000000000000000000032221256751517300260720ustar00rootroot00000000000000#!/usr/bin/python # # Copyright Divye Kapoor 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http:#www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI application on localhost # It can be accessed by http://localhost:8000/cgi-bin/requestinfo.py # It returns the query parameters passed to the CGI Script as plain text. # import cgitb; cgitb.enable() # for debugging only import cgi import os, sys sys.stdout.write( "HTTP/1.0 200 Requestinfo.py Output follows\r\n" ) sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) sys.stdout.write( "\r\n" ) form = cgi.FieldStorage() qstring = "" qstring_dict = {} print "Headers: ",form.headers if os.environ.has_key("QUERY_STRING"): qstring = os.environ["QUERY_STRING"] try: qstring_dict = cgi.parse_qs(qstring,1,1) # parse_qs(query_string,keep_blanks,strict_parsing) except ValueError: print "Error parsing query string." print "Query string:", qstring print "GET parameters:", for i in qstring_dict.keys(): print i,"-",qstring_dict[i],";", print # Remove GET params and print only the POST ones print "POST parameters:", try: for i in form.keys(): if i not in qstring_dict.keys(): print i,"-",form.getfirst(i, ""),";", print except TypeError: # In case of empty POST bodies. pass print 'HTTP HEADERS-------------------' print 'Content-Type:', os.environ.get('CONTENT_TYPE') print 'Content-Length:', os.environ.get('CONTENT_LENGTH') for k in os.environ.keys(): if k.startswith('HTTP_'): print k, ':', os.environ[k] cpp-netlib-0.11.2-final/libs/network/test/server/cgi-bin/sleep.py000077500000000000000000000003531256751517300246400ustar00rootroot00000000000000#!/usr/bin/python import os, sys, time if os.environ.has_key("QUERY_STRING") and os.environ["QUERY_STRING"].isdigit(): time.sleep(int(os.environ["QUERY_STRING"])) sys.stdout.write( "HTTP/1.0 200\r\n" ) sys.stdout.write( "\r\n" ) cpp-netlib-0.11.2-final/libs/network/test/server/cgi_server.py000066400000000000000000000016641256751517300243530ustar00rootroot00000000000000#!/usr/bin/python # # Copyright Divye Kapoor 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http:#www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI HTTP Server at port 8000 on localhost # It will be used to test the http::client interface of the library import CGIHTTPServer import BaseHTTPServer import threading from threading import Thread, Event stop_serving = Event() server_thread = None def run(server_class=BaseHTTPServer.HTTPServer, handler_class=CGIHTTPServer.CGIHTTPRequestHandler): server_address = ('',8000) httpd = server_class(server_address, handler_class) while not stop_serving.isSet(): httpd.handle_request() def start_server(): server_thread = Thread(None, run, "HTTP Server",(), None, None) server_thread.start() server_thread.join() if __name__ == '__main__': start_server() cpp-netlib-0.11.2-final/libs/network/test/server/http_test_server.py000066400000000000000000000020671256751517300256250ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright Allister Levi Sanchez 2008. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # # This program sets up a CGI HTTP Server at port 8000 on localhost # It will be used to test the http::client interface of the library import BaseHTTPServer import CGIHTTPServer import os class HttpTestHandler(CGIHTTPServer.CGIHTTPRequestHandler): def run_cgi(self): """Version of run_cgi that provides more HTTP headers.""" headers_str = '' for a in self.headers.items(): headers_str += "%s: %s\n" % a os.environ['HTTP_ALL_HEADERS'] = headers_str # run the rest of run_cgi CGIHTTPServer.CGIHTTPRequestHandler.run_cgi(self) def run_server(server_class=BaseHTTPServer.HTTPServer, handler_class=HttpTestHandler): server_address = ('',8000) httpd = server_class(server_address, handler_class) httpd.serve_forever() if __name__ == '__main__': run_server() cpp-netlib-0.11.2-final/libs/network/test/server/https_test_server.py000066400000000000000000000031711256751517300260050ustar00rootroot00000000000000#!/usr/bin/env python # Copyright 2009 Jeroen Habraken # Copyright 2009 Dean Michael Berris # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) import socket from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler from CGIHTTPServer import CGIHTTPRequestHandler from OpenSSL import SSL import os class SecureHTTPServer(HTTPServer): def __init__(self, server_address, HandlerClass): HTTPServer.__init__(self, server_address, HandlerClass) ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_privatekey_file ("key.pem") ctx.use_certificate_file("certificate.pem") self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type)) self.server_bind() self.server_activate() class SecureHTTPRequestHandler(CGIHTTPRequestHandler): def setup(self): self.connection = self.request self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) def run_cgi(self): """Version of run_cgi that provides more HTTP headers.""" headers_str = '' for a in self.headers.items(): headers_str += "%s: %s\n" % a os.environ['HTTP_ALL_HEADERS'] = headers_str # run the rest of run_cgi CGIHTTPRequestHandler.run_cgi(self) if __name__ == '__main__': SecureHTTPServer(('127.0.0.1', 8443), SecureHTTPRequestHandler).serve_forever() cpp-netlib-0.11.2-final/libs/network/test/server/key.pem000066400000000000000000000015671256751517300231460ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCwc3j9E+LMKqw2PBf/a5zLIAfNxDadFW2OB3S85kXgr72x/00o i5JiPOeA7LGrmhuJ+nDXiO+AWL1O6fOzOkyTd0Nh1hCHJzjrJEfIt3iqdQGHiocV upWN5iCQRzCrErbPvtvvs/r7mMheb9W3q9lntKPwiZ7mmr/daYdAbVuQpQIDAQAB AoGBAIJ7MXn8TZdq6uRENf7ERjMTIZIwya4JnXUM4G+b3QqVCrLottcHtxz8Krl0 zsG1+S1kTDOmaG1BseP8LyFXOC4Ni8H6vjnFG/vTzuArPhtoB9B5wXDnPfPQH22a 10XH3aGbOoyP9sg0HF0ZJsnou3QgQfg49whWa8gl8SUSckI1AkEA4NFwJ7GpVmIA ZuVzguKEKNNxC9PNUDeGUCyjH5fejolL2wIQQ4rKpml05TbUuugQByxBi+Gbd51j hGeFOncVywJBAMjsrWoOyGpDJIe2H0Aklecp9awn2H59GFNBmDvUO6LAAkr5Dkky 64QGLCZLAdswH9QaMuBvzKSZkzGcfDKwpU8CQBxTJt9Jaf1hMY3FQO1vnpkKMsb7 s3V02W5GgXLcjoTE1ZLNSsFHvkqDJOAwLVMzI7nToJqAHTdP1Bb9d/KqyEsCQA0x /fGJJwBTiIKhI0xDGtUjnE7CDyW/cWmGVUkYlxIJKh1iXd3QykbRYPTi2Cxc7Lox PkYfEYF91Hzdmgp6L2ECQFcCg0qKfvy1YeTChrDFMBrZx4yoqYGBnqEqxshksAJg o1r5HVSlO71aVgeAs/5DD4IIb2OyiJE/dv6t0L8TQeQ= -----END RSA PRIVATE KEY----- cpp-netlib-0.11.2-final/libs/network/test/server/test.xml000066400000000000000000000001611256751517300233410ustar00rootroot00000000000000 Hi! This is node 1 Node 2 here. cpp-netlib-0.11.2-final/libs/network/test/uri/000077500000000000000000000000001256751517300211335ustar00rootroot00000000000000cpp-netlib-0.11.2-final/libs/network/test/uri/CMakeLists.txt000066400000000000000000000025661256751517300237040ustar00rootroot00000000000000# Copyright (c) Dean Michael Berris 2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) if (Boost_FOUND) set( TESTS uri_test uri_builder_test uri_builder_stream_test uri_encoding_test relative_uri_test ) foreach (test ${TESTS}) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-${test} ${test}.cpp) add_dependencies(cpp-netlib-${test} cppnetlib-uri) target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-${test} ws2_32) endif() set_target_properties(cpp-netlib-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) endif() cpp-netlib-0.11.2-final/libs/network/test/uri/relative_uri_test.cpp000066400000000000000000000011411256751517300253650ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE Relative URL Test #include #include #include #include using namespace boost::network; BOOST_AUTO_TEST_CASE(relative_uri_test) { // don't yet support relative URIs uri::uri instance("example.com"); BOOST_REQUIRE(!uri::valid(instance)); } cpp-netlib-0.11.2-final/libs/network/test/uri/uri_builder_stream_test.cpp000066400000000000000000000104311256751517300265550ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE URI builder stream test #include #include #include #include #include using namespace boost::network; BOOST_AUTO_TEST_CASE(builder_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(full_uri_builder_test) { uri::uri instance; instance << uri::scheme("http") << uri::user_info("user:password") << uri::host("www.example.com") << uri::port("80") << uri::path("/path") << uri::query("query") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL( "http://user:password@www.example.com:80/path?query#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(port_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com:8000/", instance.string()); } BOOST_AUTO_TEST_CASE(encoded_path_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::encoded_path("/Path With (Some) Encoded Characters!"); ; BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL( "http://www.example.com:8000/" "Path%20With%20%28Some%29%20Encoded%20Characters%21", instance.string()); } BOOST_AUTO_TEST_CASE(query_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::query("key", "value"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/?key=value", instance.string()); } BOOST_AUTO_TEST_CASE(query_2_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::query("key1", "value1") << uri::query("key2", "value2"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/?key1=value1&key2=value2", instance.string()); } BOOST_AUTO_TEST_CASE(fragment_test) { uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(from_base_test) { uri::uri base_uri("http://www.example.com"); uri::uri instance; instance << base_uri << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(scheme_http_test) { uri::uri instance; instance << uri::schemes::http << uri::host("www.example.com") << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(scheme_https_test) { uri::uri instance; instance << uri::schemes::https << uri::host("www.example.com") << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("https://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(encoded_null_char_test) { // there is a potential bug in the way we process ranges if the // strings are null terminated. uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::encoded_path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(mailto_builder_test) { uri::uri instance; instance << uri::scheme("mailto") << uri::path("cpp-netlib@example.com"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("mailto:cpp-netlib@example.com", instance.string()); } cpp-netlib-0.11.2-final/libs/network/test/uri/uri_builder_test.cpp000066400000000000000000000105251256751517300252060ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE URI builder test #include #include #include #include using namespace boost::network; BOOST_AUTO_TEST_CASE(builder_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http").host("www.example.com").path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(full_uri_builder_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http") .user_info("user:password") .host("www.example.com") .port("80") .path("/path") .query("query") .fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL( "http://user:password@www.example.com:80/path?query#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(port_test) { uri::uri instance; uri::builder(instance).scheme("http").host("www.example.com").port(8000).path( "/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com:8000/", instance.string()); } BOOST_AUTO_TEST_CASE(encoded_path_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http").host("www.example.com").port(8000).encoded_path( "/Path With (Some) Encoded Characters!"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL( "http://www.example.com:8000/" "Path%20With%20%28Some%29%20Encoded%20Characters%21", instance.string()); } BOOST_AUTO_TEST_CASE(query_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http").host("www.example.com").path("/").query("key", "value"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/?key=value", instance.string()); } BOOST_AUTO_TEST_CASE(query_2_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http") .host("www.example.com") .path("/") .query("key1", "value1") .query("key2", "value2"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/?key1=value1&key2=value2", instance.string()); } BOOST_AUTO_TEST_CASE(fragment_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("http").host("www.example.com").path("/").fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(from_base_test) { uri::uri instance("http://www.example.com"); uri::builder builder(instance); builder.path("/").fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); } BOOST_AUTO_TEST_CASE(encoded_null_char_test) { // there is a potential bug in the way we process ranges if the // strings are null terminated. uri::uri instance; uri::builder builder(instance); builder.scheme("http").host("www.example.com").encoded_path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); } BOOST_AUTO_TEST_CASE(mailto_builder_test) { uri::uri instance; uri::builder builder(instance); builder.scheme("mailto").path("cpp-netlib@example.com"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("mailto:cpp-netlib@example.com", instance.string()); } BOOST_AUTO_TEST_CASE(ipv4_address) { using namespace boost::asio::ip; uri::uri instance; uri::builder builder(instance); builder.scheme("http").host(address_v4::loopback()).path("/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL("http://127.0.0.1/", instance.string()); } // BOOST_AUTO_TEST_CASE(ipv6_address) { // using namespace boost::asio::ip; // uri::uri instance; // uri::builder builder(instance); // builder // .scheme("http") // .host(address_v6::loopback()) // .path("/") // ; // BOOST_REQUIRE(uri::valid(instance)); // BOOST_CHECK_EQUAL("http://[::1]/", instance.string()); //} cpp-netlib-0.11.2-final/libs/network/test/uri/uri_encoding_test.cpp000066400000000000000000000031421256751517300253430ustar00rootroot00000000000000// Copyright (c) Glyn Matthews 2011. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE URL encoding test #include #include #include #include #include using namespace boost::network; BOOST_AUTO_TEST_CASE(encoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); std::string instance; uri::encode(unencoded, std::back_inserter(instance)); BOOST_CHECK_EQUAL(instance, encoded); } BOOST_AUTO_TEST_CASE(decoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); std::string instance; uri::decode(encoded, std::back_inserter(instance)); BOOST_CHECK_EQUAL(instance, unencoded); } BOOST_AUTO_TEST_CASE(encoding_multibyte_test) { const std::string unencoded("한글 테스트"); const std::string encoded("%ED%95%9C%EA%B8%80%20%ED%85%8C%EC%8A%A4%ED%8A%B8"); std::string instance; uri::encode(unencoded, std::back_inserter(instance)); BOOST_CHECK_EQUAL(instance, encoded); } BOOST_AUTO_TEST_CASE(decoding_multibyte_test) { const std::string unencoded("한글 테스트"); const std::string encoded("%ED%95%9C%EA%B8%80%20%ED%85%8C%EC%8A%A4%ED%8A%B8"); std::string instance; uri::decode(encoded, std::back_inserter(instance)); BOOST_CHECK_EQUAL(instance, unencoded); } cpp-netlib-0.11.2-final/libs/network/test/uri/uri_test.cpp000066400000000000000000000476261256751517300235140ustar00rootroot00000000000000// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn // Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt of copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE URL Test #include #include #include #include #include #include #include #include #include #include using namespace boost::network; BOOST_AUTO_TEST_CASE(basic_uri_scheme_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); } BOOST_AUTO_TEST_CASE(basic_uri_user_info_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::user_info(instance), ""); } BOOST_AUTO_TEST_CASE(basic_uri_host_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); } BOOST_AUTO_TEST_CASE(basic_uri_port_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::port(instance), ""); } BOOST_AUTO_TEST_CASE(basic_uri_path_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } BOOST_AUTO_TEST_CASE(basic_uri_query_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::query(instance), ""); } BOOST_AUTO_TEST_CASE(basic_uri_fragment_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::fragment(instance), ""); } BOOST_AUTO_TEST_CASE(basic_uri_value_semantics_test) { uri::uri original; uri::uri assigned; assigned = original; BOOST_CHECK(original == assigned); assigned = "http://www.example.com/"; BOOST_CHECK(original != assigned); uri::uri copy(assigned); BOOST_CHECK(copy == assigned); } BOOST_AUTO_TEST_CASE(basic_uri_range_scheme_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.scheme_range()); BOOST_CHECK(instance.begin() == boost::begin(instance.scheme_range())); BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); } BOOST_AUTO_TEST_CASE(basic_uri_range_user_info_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(!instance.user_info_range()); BOOST_CHECK(boost::begin(instance.host_range()) == boost::begin(instance.user_info_range())); BOOST_CHECK(boost::begin(instance.host_range()) == boost::end(instance.user_info_range())); } BOOST_AUTO_TEST_CASE(basic_uri_range_host_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.host_range()); BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); } BOOST_AUTO_TEST_CASE(basic_uri_range_port_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(!instance.port_range()); BOOST_CHECK(boost::end(instance.host_range()) == boost::begin(instance.port_range())); BOOST_CHECK(boost::end(instance.host_range()) == boost::end(instance.port_range())); } BOOST_AUTO_TEST_CASE(basic_uri_range_path_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.path_range()); BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); BOOST_CHECK(instance.end() == boost::end(instance.path_range())); } BOOST_AUTO_TEST_CASE(basic_uri_range_query_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(!instance.query_range()); BOOST_CHECK(instance.end() == boost::begin(instance.query_range())); BOOST_CHECK(instance.end() == boost::end(instance.query_range())); } BOOST_AUTO_TEST_CASE(basic_uri_range_fragment_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(!instance.fragment_range()); BOOST_CHECK(instance.end() == boost::begin(instance.fragment_range())); BOOST_CHECK(instance.end() == boost::end(instance.fragment_range())); } BOOST_AUTO_TEST_CASE(full_uri_scheme_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); } BOOST_AUTO_TEST_CASE(full_uri_user_info_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); } BOOST_AUTO_TEST_CASE(full_uri_host_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); } BOOST_AUTO_TEST_CASE(full_uri_port_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::port(instance), "80"); BOOST_CHECK(uri::port_us(instance)); BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); } BOOST_AUTO_TEST_CASE(full_uri_path_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::path(instance), "/path"); } BOOST_AUTO_TEST_CASE(full_uri_query_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::query(instance), "query"); } BOOST_AUTO_TEST_CASE(full_uri_fragment_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } BOOST_AUTO_TEST_CASE(full_uri_range_scheme_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.scheme_range()); BOOST_CHECK(instance.begin() == boost::begin(instance.scheme_range())); BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); } BOOST_AUTO_TEST_CASE(full_uri_range_user_info_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.user_info_range()); BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); } BOOST_AUTO_TEST_CASE(full_uri_range_host_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.host_range()); BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); } BOOST_AUTO_TEST_CASE(full_uri_range_port_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.port_range()); BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); } BOOST_AUTO_TEST_CASE(full_uri_range_path_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.path_range()); BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); } BOOST_AUTO_TEST_CASE(full_uri_range_query_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.query_range()); BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); } BOOST_AUTO_TEST_CASE(full_uri_range_fragment_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(instance.fragment_range()); BOOST_CHECK( boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); BOOST_CHECK(instance.end() == boost::end(instance.fragment_range())); } BOOST_AUTO_TEST_CASE(mailto_test) { uri::uri instance("mailto:john.doe@example.com"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "mailto"); BOOST_CHECK_EQUAL(uri::path(instance), "john.doe@example.com"); } BOOST_AUTO_TEST_CASE(file_test) { uri::uri instance("file:///bin/bash"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "file"); BOOST_CHECK_EQUAL(uri::path(instance), "/bin/bash"); } BOOST_AUTO_TEST_CASE(xmpp_test) { uri::uri instance( "xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "xmpp"); BOOST_CHECK_EQUAL(uri::path(instance), "example-node@example.com"); BOOST_CHECK_EQUAL(uri::query(instance), "message;subject=Hello%20World"); } BOOST_AUTO_TEST_CASE(ipv4_address_test) { uri::uri instance("http://129.79.245.252/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "129.79.245.252"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } BOOST_AUTO_TEST_CASE(ipv4_loopback_test) { uri::uri instance("http://127.0.0.1/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "127.0.0.1"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } BOOST_AUTO_TEST_CASE(ipv6_address_test_1) { uri::uri instance("http://[1080:0:0:0:8:800:200C:417A]/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "[1080:0:0:0:8:800:200C:417A]"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } BOOST_AUTO_TEST_CASE(ipv6_address_test_2) { uri::uri instance("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } // BOOST_AUTO_TEST_CASE(ipv6_loopback_test) { // uri::uri instance("http://[::1]/"); // BOOST_REQUIRE(uri::valid(instance)); // BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); // BOOST_CHECK_EQUAL(uri::host(instance), "[::1]"); // BOOST_CHECK_EQUAL(uri::path(instance), "/"); //} BOOST_AUTO_TEST_CASE(ftp_test) { uri::uri instance("ftp://john.doe@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "ftp"); BOOST_CHECK_EQUAL(uri::user_info(instance), "john.doe"); BOOST_CHECK_EQUAL(uri::host(instance), "ftp.example.com"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); } BOOST_AUTO_TEST_CASE(news_test) { uri::uri instance("news:comp.infosystems.www.servers.unix"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "news"); BOOST_CHECK_EQUAL(uri::path(instance), "comp.infosystems.www.servers.unix"); } BOOST_AUTO_TEST_CASE(tel_test) { uri::uri instance("tel:+1-816-555-1212"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "tel"); BOOST_CHECK_EQUAL(uri::path(instance), "+1-816-555-1212"); } BOOST_AUTO_TEST_CASE(encoded_uri_test) { uri::uri instance( "http://www.example.com/" "Path%20With%20%28Some%29%20Encoded%20Characters%21"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); } BOOST_AUTO_TEST_CASE(copy_constructor_test) { uri::uri instance("http://www.example.com/"); uri::uri copy = instance; BOOST_CHECK_EQUAL(instance, copy); } BOOST_AUTO_TEST_CASE(assignment_test) { uri::uri instance("http://www.example.com/"); uri::uri copy; copy = instance; BOOST_CHECK_EQUAL(instance, copy); } BOOST_AUTO_TEST_CASE(swap_test) { uri::uri instance("http://www.example.com/"); uri::uri copy("http://www.example.org/"); uri::swap(instance, copy); BOOST_CHECK_EQUAL(instance.string(), "http://www.example.org/"); BOOST_CHECK_EQUAL(copy.string(), "http://www.example.com/"); } BOOST_AUTO_TEST_CASE(equality_test) { uri::uri uri_1("http://www.example.com/"); uri::uri uri_2("http://www.example.com/"); BOOST_CHECK(uri_1 == uri_2); } BOOST_AUTO_TEST_CASE(equality_test_1) { uri::uri uri_1("http://www.example.com/"); std::string uri_2("http://www.example.com/"); BOOST_CHECK(uri_1 == uri_2); } BOOST_AUTO_TEST_CASE(equality_test_2) { std::string uri_1("http://www.example.com/"); uri::uri uri_2("http://www.example.com/"); BOOST_CHECK(uri_1 == uri_2); } BOOST_AUTO_TEST_CASE(equality_test_3) { uri::uri uri_1("http://www.example.com/"); std::string uri_2("http://www.example.com/"); BOOST_CHECK(uri_1 == uri_2.c_str()); } BOOST_AUTO_TEST_CASE(equality_test_4) { std::string uri_1("http://www.example.com/"); uri::uri uri_2("http://www.example.com/"); BOOST_CHECK(uri_1.c_str() == uri_2); } BOOST_AUTO_TEST_CASE(inequality_test) { uri::uri uri_1("http://www.example.com/"); uri::uri uri_2("http://www.example.com/"); BOOST_CHECK(!(uri_1 != uri_2)); } BOOST_AUTO_TEST_CASE(less_than_test) { // uri_1 is lexicographically less than uri_2 uri::uri uri_1("http://www.example.com/"); uri::uri uri_2("http://www.example.org/"); BOOST_CHECK(uri_1 < uri_2); } BOOST_AUTO_TEST_CASE(username_test) { uri::uri instance("ftp://john.doe@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::username(instance), "john.doe"); } BOOST_AUTO_TEST_CASE(pasword_test) { uri::uri instance("ftp://john.doe:password@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::password(instance), "password"); } BOOST_AUTO_TEST_CASE(hierarchical_part_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::hierarchical_part(instance), "user:password@www.example.com:80/path"); } BOOST_AUTO_TEST_CASE(partial_hierarchical_part_test) { uri::uri instance("http://www.example.com?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::hierarchical_part(instance), "www.example.com"); } BOOST_AUTO_TEST_CASE(authority_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); } BOOST_AUTO_TEST_CASE(partial_authority_test) { uri::uri instance("http://www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::authority(instance), "www.example.com"); } BOOST_AUTO_TEST_CASE(http_query_map_test) { uri::uri instance( "http://user:password@www.example.com:80/path?query=something#fragment"); BOOST_REQUIRE(uri::valid(instance)); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); BOOST_CHECK_EQUAL(queries.begin()->first, "query"); BOOST_CHECK_EQUAL(queries.begin()->second, "something"); } BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { uri::uri instance( "xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); BOOST_CHECK_EQUAL(queries.begin()->first, "message"); BOOST_CHECK_EQUAL(queries.begin()->second, ""); BOOST_CHECK_EQUAL((++queries.begin())->first, "subject"); BOOST_CHECK_EQUAL((++queries.begin())->second, "Hello%20World"); } BOOST_AUTO_TEST_CASE(range_test) { const std::string url("http://www.example.com/"); uri::uri instance(url); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } BOOST_AUTO_TEST_CASE(issue_67_test) { // https://github.com/cpp-netlib/cpp-netlib/issues/67 const std::string site_name("http://www.google.com"); uri::uri bar0; uri::uri bar1 = site_name; bar0 = site_name; BOOST_CHECK(uri::is_valid(bar0)); BOOST_CHECK(uri::is_valid(bar1)); } BOOST_AUTO_TEST_CASE(from_parts_1) { BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path?query#fragment"), uri::from_parts(uri::uri("http://www.example.com"), "/path", "query", "fragment")); } BOOST_AUTO_TEST_CASE(from_parts_2) { BOOST_CHECK_EQUAL( uri::uri("http://www.example.com/path?query#fragment"), uri::from_parts("http://www.example.com", "/path", "query", "fragment")); } BOOST_AUTO_TEST_CASE(from_parts_3) { BOOST_CHECK_EQUAL( uri::uri("http://www.example.com/path?query"), uri::from_parts("http://www.example.com", "/path", "query")); } BOOST_AUTO_TEST_CASE(from_parts_4) { BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path"), uri::from_parts("http://www.example.com", "/path")); } BOOST_AUTO_TEST_CASE(from_file) { boost::filesystem::path path("/a/path/to/a/file.txt"); BOOST_CHECK_EQUAL(uri::uri("file:///a/path/to/a/file.txt"), uri::from_file(path)); } BOOST_AUTO_TEST_CASE(issue_104_test) { // https://github.com/cpp-netlib/cpp-netlib/issues/104 boost::scoped_ptr instance(new uri::uri("http://www.example.com/")); uri::uri copy = *instance; instance.reset(); BOOST_CHECK_EQUAL(uri::scheme(copy), "http"); } BOOST_AUTO_TEST_CASE(uri_set_test) { std::set uri_set; uri_set.insert(uri::uri("http://www.example.com/")); BOOST_REQUIRE(!uri_set.empty()); BOOST_CHECK_EQUAL((*uri_set.begin()), uri::uri("http://www.example.com/")); } BOOST_AUTO_TEST_CASE(uri_unordered_set_test) { boost::unordered_set uri_set; uri_set.insert(uri::uri("http://www.example.com/")); BOOST_REQUIRE(!uri_set.empty()); BOOST_CHECK_EQUAL((*uri_set.begin()), uri::uri("http://www.example.com/")); } BOOST_AUTO_TEST_CASE(issue_161_test) { uri::uri instance( "http://www.example.com/" "path?param1=-¶m2=some+plus+encoded+text¶m3=~"); BOOST_REQUIRE(uri::valid(instance)); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(3)); BOOST_CHECK_EQUAL(queries["param1"], "-"); BOOST_CHECK_EQUAL(queries["param2"], "some+plus+encoded+text"); BOOST_CHECK_EQUAL(queries["param3"], "~"); BOOST_CHECK_EQUAL(uri::decoded(queries["param2"]), "some plus encoded text"); } BOOST_AUTO_TEST_CASE(issue_364_test) { uri::uri instance; uri::schemes::http(instance) << uri::host("my.awesome.server.com"); BOOST_CHECK_EQUAL("my.awesome.server.com", uri::authority(instance)); } BOOST_AUTO_TEST_CASE(issue_447_test) { uri::uri instance("http://[www.foo.com/"); BOOST_REQUIRE(!uri::valid(instance)); } BOOST_AUTO_TEST_CASE(issue_499_test) { uri::uri instance( "http://www.example.com/path?param1¶m2=¶m3=value"); BOOST_REQUIRE(uri::valid(instance)); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(3)); BOOST_CHECK_EQUAL(queries["param1"], ""); BOOST_CHECK_EQUAL(queries["param2"], ""); BOOST_CHECK_EQUAL(queries["param3"], "value"); } cpp-netlib-0.11.2-final/libs/network/test/utils_base64_test.cpp000066400000000000000000000160401256751517300244040ustar00rootroot00000000000000#define BOOST_TEST_MODULE BASE64 Test #include #include #include #include #include #include #include #include #include #include using namespace boost::network::utils; // proves that all public functions are compilable; the result check // is very minimum here, so that the test doesn't look so stupid ;-) BOOST_AUTO_TEST_CASE(interface_test) { std::string result; base64::state state; // check string literal BOOST_CHECK_EQUAL(base64::encode("abc"), "YWJj"); base64::encode("abc", std::back_inserter(result)); BOOST_CHECK_EQUAL(result, "YWJj"); result.clear(); base64::encode("abc", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWJj"); // check std::string std::string input("abc"); BOOST_CHECK_EQUAL(base64::encode(input), "YWJj"); result.clear(); base64::encode(input, std::back_inserter(result)); BOOST_CHECK_EQUAL(result, "YWJj"); result.clear(); base64::encode(input.begin(), input.end(), std::back_inserter(result)); BOOST_CHECK_EQUAL(result, "YWJj"); result.clear(); base64::encode(input, std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWJj"); result.clear(); base64::encode(input.begin(), input.end(), std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWJj"); // check array of chars char char_array[] = {'a', 'b', 'c', 0}; BOOST_CHECK_EQUAL(base64::encode(char_array), "YWJj"); // check boost::array of chars boost::array char_boost_array = {{'a', 'b', 'c'}}; BOOST_CHECK_EQUAL(base64::encode(char_boost_array), "YWJj"); // check std::vector of chars std::vector char_vector(char_array, char_array + 3); BOOST_CHECK_EQUAL(base64::encode(char_vector), "YWJj"); // check array of ints int int_array[] = {'a', 'b', 'c'}; BOOST_CHECK_EQUAL(base64::encode(int_array), "YWJj"); // check boost::array of ints boost::array int_boost_array = {{'a', 'b', 'c'}}; BOOST_CHECK_EQUAL(base64::encode(int_boost_array), "YWJj"); // check std::vector of ints std::vector int_vector(int_array, int_array + 3); BOOST_CHECK_EQUAL(base64::encode(int_vector), "YWJj"); // check that base64::encode_rest is compilable and callable result.clear(); base64::encode_rest(std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, ""); // check that the iostream interface is compilable and callable std::ostringstream output; output << base64::io::encode("abc") << base64::io::encode(input.begin(), input.end()) << base64::io::encode(int_array) << base64::io::encode(int_boost_array) << base64::io::encode(char_array) << base64::io::encode(char_boost_array) << base64::io::encode(char_vector) << base64::io::encode_rest; BOOST_CHECK_EQUAL(output.str(), "YWJjYWJjYWJjYWJjYWJjYWJjYWJj"); } // checks that functions encoding a single chunk append the correct padding // if the input byte count is not divisible by 3 BOOST_AUTO_TEST_CASE(padding_test) { BOOST_CHECK_EQUAL(base64::encode(""), ""); BOOST_CHECK_EQUAL(base64::encode("a"), "YQ=="); BOOST_CHECK_EQUAL(base64::encode("aa"), "YWE="); BOOST_CHECK_EQUAL(base64::encode("aaa"), "YWFh"); } // check that functions using encoding state interrupt and resume encoding // correcly if the byte count of the partial input is not divisible by 3 BOOST_AUTO_TEST_CASE(state_test) { base64::state state; std::string result; // check encoding empty input; including the state value base64::encode("", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, ""); BOOST_CHECK(state.empty()); result.clear(); state.clear(); // check one third of quantum which needs two character padding; // including how the state develops when encoded by single character base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "Y"); BOOST_CHECK(!state.empty()); base64::encode_rest(std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YQ=="); BOOST_CHECK(state.empty()); result.clear(); state.clear(); // check two thirds of quantum which needs one character padding; // including how the state develops when encoded by single character base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "Y"); BOOST_CHECK(!state.empty()); base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YW"); BOOST_CHECK(!state.empty()); base64::encode_rest(std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWE="); BOOST_CHECK(state.empty()); result.clear(); state.clear(); // check a complete quantum which needs no padding; including // how the state develops when encoded by single character base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "Y"); BOOST_CHECK(!state.empty()); base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YW"); BOOST_CHECK(!state.empty()); base64::encode("a", std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWFh"); BOOST_CHECK(state.empty()); base64::encode_rest(std::back_inserter(result), state); BOOST_CHECK_EQUAL(result, "YWFh"); BOOST_CHECK(state.empty()); } // checks that the base64 output can be returned as wchar_t too BOOST_AUTO_TEST_CASE(wide_character_test) { BOOST_CHECK(base64::encode("abc") == L"YWJj"); BOOST_CHECK(base64::encode(std::string("abc")) == L"YWJj"); std::wostringstream output; output << base64::io::encode("abc") << base64::io::encode_rest; BOOST_CHECK(output.str() == L"YWJj"); } // checks that the base64-io manipulators are compilable and work BOOST_AUTO_TEST_CASE(io_test) { // check complete quantum where no state has to be remembered std::ostringstream output; output << base64::io::encode("abc") << base64::io::encode_rest; BOOST_CHECK_EQUAL(output.str(), "YWJj"); // check that encode_rest clears the state output.str(""); output << base64::io::encode("a"); BOOST_CHECK(!base64::io::empty_state(output)); output << base64::io::encode_rest; BOOST_CHECK(base64::io::empty_state(output)); // check that forced clearing the state works output.str(""); output << base64::io::encode("a"); BOOST_CHECK(!base64::io::empty_state(output)); output << base64::io::clear_state; BOOST_CHECK(base64::io::empty_state(output)); // check one third of quantum which has to be remembered in state output.str(""); output << base64::io::encode("a") << base64::io::encode("bc") << base64::io::encode_rest; BOOST_CHECK_EQUAL(output.str(), "YWJj"); // check two thirds of quantum which have to be remembered in state. output.str(""); output << base64::io::encode("ab") << base64::io::encode("c") << base64::io::encode_rest; BOOST_CHECK_EQUAL(output.str(), "YWJj"); } cpp-netlib-0.11.2-final/libs/network/test/utils_thread_pool.cpp000066400000000000000000000026361256751517300245670ustar00rootroot00000000000000 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE utils thread pool test #include #include #include #include using namespace boost::network; // This test specifies the requirements for a thread pool interface. At the // very least any thread pool implementation should be able to pass the simple // tests that this unit test requires of thread pools. Ultimately the // requirements will show up in the Concept documentation, but this test is the // canonical definition of what a thread pool should look like at least // syntactically. // BOOST_AUTO_TEST_CASE(default_constructor) { utils::thread_pool pool; BOOST_CHECK_EQUAL(pool.thread_count(), std::size_t(1)); } struct foo { foo() : val_(0) {} void bar(int val) { val_ += val; } int const val() const { return val_; } protected: int val_; }; BOOST_AUTO_TEST_CASE(post_work) { foo instance; { utils::thread_pool pool; BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 1))); BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 2))); // require that pool is destroyed here, RAII baby } BOOST_CHECK_EQUAL(instance.val(), 3); } cpp-netlib-0.11.2-final/package.sh000077500000000000000000000033321256751517300166660ustar00rootroot00000000000000#!/bin/sh # # Copyright 2012 Dean Michael Berris # Copyright 2012 Google, Inc. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # VERSION="$1" if [ "$VERSION" = "" ]; then VERSION="`git log --format=oneline | awk '{print $1}' | head -1`" fi # Break down the version in form "M.m.p" into individual variables. BOOST_NETLIB_VERSION_MAJOR=`echo $VERSION | sed 's/[\._\-]/ /g' | awk '{print $1}'` BOOST_NETLIB_VERSION_MINOR=`echo $VERSION | sed 's/[\._\-]/ /g' | awk '{print $2}'` BOOST_NETLIB_VERSION_INCREMENT=`echo $VERSION | sed 's/[\._\-]/ /g' | awk '{print $3}'` echo $BOOST_NETLIB_VERSION_MAJOR echo $BOOST_NETLIB_VERSION_MINOR echo $BOOST_NETLIB_VERSION_INCREMENT # Then update the version. sed -i '' 's/BOOST_NETLIB_VERSION_MAJOR [0-9]*/BOOST_NETLIB_VERSION_MAJOR '$BOOST_NETLIB_VERSION_MAJOR'/g' boost/network/version.hpp sed -i '' 's/BOOST_NETLIB_VERSION_MINOR [0-9]*/BOOST_NETLIB_VERSION_MINOR '$BOOST_NETLIB_VERSION_MINOR'/g' boost/network/version.hpp sed -i '' 's/BOOST_NETLIB_VERSION_INCREMENT [0-9]*/BOOST_NETLIB_VERSION_INCREMENT '$BOOST_NETLIB_VERSION_INCREMENT'/g' boost/network/version.hpp # Show the diff git diff boost/network/version.hpp # Commit the change git add boost/network/version.hpp git commit -m"Bumping release number to $VERSION" TAG="cpp-netlib-$VERSION" git tag $TAG echo "Tagged $TAG." git archive --prefix=cpp-netlib-$VERSION/ --format=zip $TAG >cpp-netlib-$VERSION.zip git archive --prefix=cpp-netlib-$VERSION/ --format=tar $TAG | gzip >cpp-netlib-$VERSION.tar.gz git archive --prefix=cpp-netlib-$VERSION/ --format=tar $TAG | bzip2 >cpp-netlib-$VERSION.tar.bz2 echo "Packaged $TAG."