FS-2746 --resolve large xmlrpc update thanks garmt

This commit is contained in:
Jeff Lenk
2012-10-13 11:37:25 -05:00
parent 37ecad9903
commit 6b6c83a718
397 changed files with 41822 additions and 33841 deletions
+8 -8
View File
@@ -41,10 +41,10 @@
Builtin events are fired by the core at various points in the execution of the application and custom events can be
reserved and registered so events from an external module can be rendered and handled by an another even handler module.
If the work time to process an event in a callback is anticipated to grow beyond a very small amount of time it is reccommended
that you impelment your own handler thread and FIFO queue so you can accept the events int the callback and queue them
into your own thread rather than tie up the delivery agent. It is in to opinion of the author that such a necessity
should be judged on a per-use basis and therefore does not fall within the scope of this system to provide that
If the work time to process an event in a callback is anticipated to grow beyond a very small amount of time it is recommended
that you implement your own handler thread and FIFO queue so you can accept the events in the callback and queue them
into your own thread rather than tie up the delivery agent. It is in the opinion of the author that such a necessity
should be judged on a per-use basis and therefore it does not fall within the scope of this system to provide that
functionality at a core level.
*/
@@ -294,7 +294,7 @@ SWITCH_DECLARE(switch_status_t) switch_name_event(const char *name, switch_event
\param owner the owner of the event name
\param subclass_name the name to reserve
\return SWITCH_STATUS_SUCCESS if the name was reserved
\note There is nothing to enforce this but I reccommend using module::event_name for the subclass names
\note There is nothing to enforce this but I recommend using module::event_name for the subclass names
*/
SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name);
@@ -302,7 +302,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const cha
SWITCH_DECLARE(switch_status_t) switch_event_free_subclass_detailed(const char *owner, const char *subclass_name);
/*!
\brief Render a string representation of an event sutable for printing or network transport
\brief Render a string representation of an event suitable for printing or network transport
\param event the event to render
\param str a string pointer to point at the allocated data
\param encode url encode the headers
@@ -319,7 +319,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_array_pair(switch_event_t **
#ifndef SWIG
/*!
\brief Render a XML representation of an event sutable for printing or network transport
\brief Render a XML representation of an event suitable for printing or network transport
\param event the event to render
\param fmt optional body of the event (varargs see standard sprintf family)
\return the xml object if the operation was successful
@@ -329,7 +329,7 @@ SWITCH_DECLARE(switch_xml_t) switch_event_xmlize(switch_event_t *event, const ch
#endif
/*!
\brief Determine if the event system has been initilized
\brief Determine if the event system has been initialized
\return SWITCH_STATUS_SUCCESS if the system is running
*/
SWITCH_DECLARE(switch_status_t) switch_event_running(void);
+5 -3
View File
@@ -198,7 +198,7 @@ SWITCH_DECLARE(const char *) switch_xml_attr(_In_opt_ switch_xml_t xml, _In_opt_
///\return the value
SWITCH_DECLARE(const char *) switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr);
///\brief Traverses the switch_xml sturcture to retrieve a specific subtag. Takes a
///\brief Traverses the switch_xml structure to retrieve a specific subtag. Takes a
///\ variable length list of tag names and indexes. The argument list must be
///\ terminated by either an index of -1 or an empty string tag name. Example:
///\ title = switch_xml_get(library, "shelf", 0, "book", 2, "title", -1);
@@ -208,13 +208,15 @@ SWITCH_DECLARE(const char *) switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_
///\return an xml node or NULL
SWITCH_DECLARE(switch_xml_t) switch_xml_get(_In_ switch_xml_t xml,...);
///\brief Converts an switch_xml structure back to xml. Returns a string of xml data that
///\brief Converts an switch_xml structure back to xml in html format. Returns a string of html data that
///\ must be freed.
///\param xml the xml node
///\param prn_header add <?xml version..> header too
///\return the xml text string
///\return the ampersanded html text string to display xml
SWITCH_DECLARE(char *) switch_xml_toxml(_In_ switch_xml_t xml, _In_ switch_bool_t prn_header);
SWITCH_DECLARE(char *) switch_xml_toxml_nolock(switch_xml_t xml, _In_ switch_bool_t prn_header);
SWITCH_DECLARE(char *) switch_xml_tohtml(_In_ switch_xml_t xml, _In_ switch_bool_t prn_header);
///\brief Converts an switch_xml structure back to xml using the buffer passed in the parameters.
///\param xml the xml node
///\param buf buffer to use
File diff suppressed because it is too large Load Diff
+7 -3
View File
@@ -483,10 +483,14 @@ SWITCH_STANDARD_API(lua_api_function)
}
if ((error = lua_parse_and_execute(L, mycmd))) {
if (switch_event_get_header(stream->param_event, "http-host")) {
stream->write_function(stream, "Content-Type: text/html\n\n<H2>Error Executing Script</H2>");
char * http = switch_event_get_header(stream->param_event, "http-uri");
if (http && (!strncasecmp(http, "/api/", 5) || !strncasecmp(http, "/webapi/", 8))) {
/* api -> fs api streams the Content-Type e.g. text/html or text/xml */
/* api -> default Content-Type is text/plain */
/* webapi, txtapi -> Content-Type defined in mod_xmlrpc text/html resp. text/plain */
stream->write_function(stream, "<H2>Error Executing Script</H2>");
} else {
stream->write_function(stream, "-ERR encountered\n");
stream->write_function(stream, "-ERR Cannot execute script\n");
}
}
lua_uninit(L);
+17 -10
View File
@@ -1,7 +1,8 @@
BASE=../../../..
XMLRPC_DIR=$(BASE)/libs/xmlrpc-c
LOCAL_OBJS = $(XMLRPC_DIR)/lib/libutil/asprintf.o\
LOCAL_OBJS = $(XMLRPC_DIR)/src/version.o\
$(XMLRPC_DIR)/lib/libutil/asprintf.o\
$(XMLRPC_DIR)/lib/util/casprintf.o\
$(XMLRPC_DIR)/lib/abyss/src/channel.o\
$(XMLRPC_DIR)/lib/abyss/src/chanswitch.o\
@@ -22,6 +23,7 @@ $(XMLRPC_DIR)/lib/libutil/make_printable.o\
$(XMLRPC_DIR)/lib/libutil/memblock.o\
$(XMLRPC_DIR)/src/method.o\
$(XMLRPC_DIR)/src/parse_value.o\
$(XMLRPC_DIR)/src/parse_datetime.o\
$(XMLRPC_DIR)/src/registry.o\
$(XMLRPC_DIR)/src/resource.o\
$(XMLRPC_DIR)/lib/abyss/src/response.o\
@@ -40,7 +42,8 @@ $(XMLRPC_DIR)/lib/abyss/src/token.o\
$(XMLRPC_DIR)/src/trace.o\
$(XMLRPC_DIR)/lib/abyss/src/trace.o\
$(XMLRPC_DIR)/lib/libutil/utf8.o\
$(XMLRPC_DIR)/src/version.o\
$(XMLRPC_DIR)/lib/libutil/string_number.o\
$(XMLRPC_DIR)/lib/libutil/base64.o\
$(XMLRPC_DIR)/lib/expat/xmlparse/xmlparse.o\
$(XMLRPC_DIR)/lib/expat/xmltok/xmlrole.o\
$(XMLRPC_DIR)/src/xmlrpc_array.o\
@@ -59,14 +62,6 @@ $(XMLRPC_DIR)/src/xmlrpc_string.o\
$(XMLRPC_DIR)/src/xmlrpc_struct.o\
$(XMLRPC_DIR)/lib/expat/xmltok/xmltok.o
#XMLRPCLAS = $(XMLRPC_DIR)/src/libxmlrpc.a
#dont ask...
#XMLRPCLAS = $(XMLRPC_DIR)/src/*.o
#XMLRPCLAS += $(XMLRPC_DIR)/src/libxmlrpc_server.so $(XMLRPC_DIR)/src/libxmlrpc.so
#XMLRPCLAS += $(XMLRPC_DIR)/src/libxmlrpc_server_abyss.so $(XMLRPC_DIR)/lib/abyss/src/libxmlrpc_abyss.so
#XMLRPCLAS += $(XMLRPC_DIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.so $(XMLRPC_DIR)/lib/expat/xmltok/libxmlrpc_xmltok.so
#LOCAL_LIBADD =$(XMLRPCLAS)
LOCAL_CFLAGS = -w -I$(XMLRPC_DIR)/lib/expat/xmlparse -I$(XMLRPC_DIR)/lib/expat/xmltok -I$(XMLRPC_DIR) -I$(XMLRPC_DIR)/include
LOCAL_CFLAGS+= -I$(XMLRPC_DIR)/lib/abyss/src -I$(XMLRPC_DIR)/lib/util/include -D_THREAD -D__EXTENSIONS__
@@ -81,3 +76,15 @@ $(XMLRPC_DIR)/lib/expat/xmltok/xmltok.o: $(XMLRPC_DIR)/lib/expat/xmltok/nametab.
$(XMLRPC_DIR)/lib/expat/xmltok/nametab.h:
cd $(XMLRPC_DIR)/lib/expat/gennmtab && $(MAKE)
cd $(XMLRPC_DIR)/lib/expat/xmltok && ../gennmtab/gennmtab > nametab.h
$(XMLRPC_DIR)/src/version.o: $(XMLRPC_DIR)/version.h
$(XMLRPC_DIR)/version.h:
cd $(XMLRPC_DIR) && $(MAKE) version.h
cd $(XMLRPC_DIR)/include && $(MAKE) xmlrpc-c/config.h
local_clean:
cd $(XMLRPC_DIR) && $(MAKE) clean
@@ -1,167 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_xml_rpc</ProjectName>
<ProjectGuid>{CBEC7225-0C21-4DA8-978E-1F158F8AD950}</ProjectGuid>
<RootNamespace>mod_xml_rpc</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
<Import Project="..\..\..\..\w32\curl.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
<Import Project="..\..\..\..\w32\curl.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
<Import Project="..\..\..\..\w32\curl.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
<Import Project="..\..\..\..\w32\curl.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\abyss\src;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\util\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\Windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\..\..\..\libs\xmlrpc\lib;..\..\..\..\libs\xmlrpc\lib\abyss\src\$(OutDir);..\..\..\..\libs\apr-util\xml\expat\lib\LibD;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\abyss\src;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\util\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\Windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\abyss\src;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\util\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\Windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\..\..\..\libs\xmlrpc\lib;..\..\..\..\libs\xmlrpc\lib\abyss\src\$(OutDir);..\..\..\..\libs\apr-util\xml\expat\lib\LibR;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\abyss\src;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\lib\util\include;%(RootDir)%(Directory)..\..\..\..\libs\xmlrpc-c\Windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_xml_rpc.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\curl\curllib.2010.vcxproj">
<Project>{87ee9da4-de1e-4448-8324-183c98dca588}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\xmlrpc-c\Windows\abyss.2010.vcxproj">
<Project>{d2396dd7-7d38-473a-abb7-6f96d65ae1b9}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\xmlrpc-c\Windows\xmlparse.2010.vcxproj">
<Project>{0d108721-eae8-4baf-8102-d8960ec93647}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\xmlrpc-c\Windows\xmlrpc.2010.vcxproj">
<Project>{cee544a9-0303-44c2-8ece-efa7d7bcbbba}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\xmlrpc-c\Windows\xmltok.2010.vcxproj">
<Project>{b535402e-38d2-4d54-8360-423acbd17192}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_xml_rpc</ProjectName>
<ProjectGuid>{CBEC7225-0C21-4DA8-978E-1F158F8AD950}</ProjectGuid>
<RootNamespace>mod_xml_rpc</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)libs\xmlrpc-c\include;$(SolutionDir)libs\xmlrpc-c\lib\abyss\src;$(SolutionDir)libs\xmlrpc-c\lib\util\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\..\..\..\libs\xmlrpc\lib;..\..\..\..\libs\xmlrpc\lib\abyss\src\$(OutDir);..\..\..\..\libs\apr-util\xml\expat\lib\LibD;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)libs\xmlrpc-c\include;$(SolutionDir)libs\xmlrpc-c\lib\abyss\src;$(SolutionDir)libs\xmlrpc-c\lib\util\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)libs\xmlrpc-c\include;$(SolutionDir)libs\xmlrpc-c\lib\abyss\src;$(SolutionDir)libs\xmlrpc-c\lib\util\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\..\..\..\libs\xmlrpc\lib;..\..\..\..\libs\xmlrpc\lib\abyss\src\$(OutDir);..\..\..\..\libs\apr-util\xml\expat\lib\LibR;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)libs\xmlrpc-c\include;$(SolutionDir)libs\xmlrpc-c\lib\abyss\src;$(SolutionDir)libs\xmlrpc-c\lib\util\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ABYSS_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_xml_rpc.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\xmlrpc-c\abyss.2010.vcxproj">
<Project>{d2396dd7-7d38-473a-abb7-6f96d65ae1b9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\xmlrpc-c\xmlparse.2010.vcxproj">
<Project>{0d108721-eae8-4baf-8102-d8960ec93647}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\xmlrpc-c\xmlrpc.2010.vcxproj">
<Project>{cee544a9-0303-44c2-8ece-efa7d7bcbbba}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\xmlrpc-c\xmltok.2010.vcxproj">
<Project>{b535402e-38d2-4d54-8360-423acbd17192}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+288 -187
View File
@@ -1,4 +1,4 @@
/*
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
@@ -22,13 +22,38 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Anthony Minessale II <anthm@freeswitch.org>
* John Wehle <john@feith.com>
*
* Garmt Boekholt <garmt@cimico.com>
*
* mod_xml_rpc.c -- XML RPC
*
* embedded webserver for FS
* exposes fs api to web (and ajax, javascript, ...)
* supports GET/POST requests (as defined below)
* and similar XMLRPC format /RPC2 freeswitch.api and management.api
*
* usage:
* (1) http:/host:port/[txt|web|xml]api/fsapicommand[?arg[ arg]*][ &key=value[+&key=value]*]
* e.g. http:/host:port/api/show?calls &refresh=5+&weather=nice
* (2) http:/host:port/filepath - serves files from conf/htdocs
*
* NB:
* ad (1) - key/value pairs are propagated as event headers
* - if &key=value is "&refresh=xx" - special feature: automatic refresh after xx sec (triggered by browser)
* note that refresh works only
* IF response content-type: text/html (i.e. "webapi" or "api")
* AND fs api command created an event header HTTP-REFRESH before the first write_stream
* NOTE if "api", fs api command has to overwrite content-type to be text/html i.s.o. text/plain (default)
*
* - if api format is "api" mod_xml_rpc will automatically assume plain/text (so webunaware fs commands are rendered apropriately)
* - xmlapi doesn't seem to be used, however if a fs api command renders xml, you can set the format type to xml
* txtapi-text/plain or webapi-text/html surround xml with <pre> xml <pre/>
* - typically fs api command arguments are encoded with UrlPathEncode (spaces -> %20), and k/v pairs are urlencoded (space -> +)
*
* ad (2) ms ie may show extra empty lines when serving large txt files as ie has problems rendering content-type "plain/text"
*
*/
#include <switch.h>
#include <switch_version.h>
@@ -40,16 +65,17 @@
#include <xmlrpc-c/abyss.h>
#include <xmlrpc-c/server.h>
#include <xmlrpc-c/server_abyss.h>
#include "../../libs/xmlrpc-c/lib/abyss/src/token.h"
#include "http.h"
#include "session.h"
#include <xmlrpc-c/base64_int.h>
#include <../lib/abyss/src/token.h>
#include <../lib/abyss/src/http.h>
#include <../lib/abyss/src/session.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime);
SWITCH_MODULE_DEFINITION(mod_xml_rpc, mod_xml_rpc_load, mod_xml_rpc_shutdown, mod_xml_rpc_runtime);
static abyss_bool HTTPWrite(TSession * s, char *buffer, uint32_t len);
static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len);
static struct {
uint16_t port;
@@ -60,6 +86,7 @@ static struct {
char *default_domain;
switch_bool_t virtual_host;
TServer abyssServer;
xmlrpc_registry *registryP;
} globals;
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_realm, globals.realm);
@@ -86,18 +113,20 @@ static switch_status_t do_config(void)
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "auth-realm")) {
realm = val;
} else if (!strcasecmp(var, "auth-user")) {
user = val;
} else if (!strcasecmp(var, "auth-pass")) {
pass = val;
} else if (!strcasecmp(var, "http-port")) {
globals.port = (uint16_t) atoi(val);
} else if (!strcasecmp(var, "default-domain")) {
default_domain = val;
} else if (!strcasecmp(var, "virtual-host")) {
globals.virtual_host = switch_true(val);
if (!zstr(var) && !zstr(val)) {
if (!strcasecmp(var, "auth-realm")) {
realm = val;
} else if (!strcasecmp(var, "auth-user")) {
user = val;
} else if (!strcasecmp(var, "auth-pass")) {
pass = val;
} else if (!strcasecmp(var, "http-port")) {
globals.port = (uint16_t) atoi(val);
} else if (!strcasecmp(var, "default-domain")) {
default_domain = val;
} else if (!strcasecmp(var, "virtual-host")) {
globals.virtual_host = switch_true(val);
}
}
}
}
@@ -135,7 +164,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)
static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
{
TSession *r = handle->data;
TSession *r = (TSession *) handle->data;
return HTTPWrite(r, (char *) data, (uint32_t) datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
@@ -143,19 +172,59 @@ static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uin
static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
{
va_list ap;
TSession *r = handle->data;
int ret = 0;
TSession *r = (TSession *) handle->data;
int ret = 1;
char *data;
switch_event_t *evnt = handle->param_event;
va_list ap;
va_start(ap, fmt);
ret = switch_vasprintf(&data, fmt, ap);
va_end(ap);
if (data) {
ret = 0;
HTTPWrite(r, data, (uint32_t) strlen(data));
free(data);
/* Stream Content-Type (http header) to the xmlrpc (web) client, if fs api command did not do it yet. */
/* If (Content-Type in event) then the header was already replied. */
/* If fs api command is not "web aware", this will set the Content-Type to "text/plain". */
const char *http_refresh = NULL;
const char *ct = NULL;
const char *refresh = NULL;
if (evnt && !(ct = switch_event_get_header(evnt, "Content-Type"))){
const char *val = switch_stristr("Content-Type", data);
if (!val) {
val = "Content-Type: text/plain\r\n\r\n";
ret = HTTPWrite(r, val, (uint32_t) strlen(val));
}
/* flag to prevent running this more than once per http reply */
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", strstr(val,":")+2);
ct = switch_event_get_header(evnt, "Content-Type");
}
if (ret) {
ret = HTTPWrite(r, data, (uint32_t) strlen(data));
}
switch_safe_free(data);
/* e.g. "http://www.cluecon.fs/api/show?calls &refresh=5" */
/* fs api command can set event header "HTTP-REFRESH" so that the web page will automagically refresh, if */
/* "refresh=xxx" was part of the http query kv pairs */
if (ret && ct && *ct && (http_refresh = switch_event_get_header(evnt, "HTTP-REFRESH"))
&& (refresh = switch_event_get_header(evnt, "refresh"))
&& !strstr("text/html", ct)
&& (atoi(refresh) > 0 )) {
const char *query = switch_event_get_header(evnt, "HTTP-QUERY");
const char *uri = switch_event_get_header(evnt, "HTTP-URI");
if (uri && query && *uri && *query) {
char *buf = switch_mprintf("<META HTTP-EQUIV=REFRESH CONTENT=\"%s; URL=%s?%s\">\n", refresh, uri, query);
ret = HTTPWrite(r, buf, (uint32_t) strlen(buf));
switch_safe_free(buf);
}
}
/* only one refresh meta header per reply */
if (http_refresh) {
switch_event_del_header(evnt, "HTTP-REFRESH");
}
}
return ret ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
@@ -192,7 +261,7 @@ static abyss_bool user_attributes(const char *user, const char *domain_name,
switch_event_destroy(&params);
return FALSE;
}
switch_event_destroy(&params);
alias = switch_xml_attr(x_user, "number-alias");
@@ -241,9 +310,8 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
char *dp;
char *dup = NULL;
char *argv[256] = { 0 };
char *status = NULL;
int argc = 0, i = 0, ok = 0;
int err = 403;
unsigned int err = 403;
if (!r) {
return FALSE;
@@ -273,7 +341,7 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
goto end;
}
err = 686;
if (!user_attributes(user, domain_name, NULL, NULL, NULL, &allowed_commands)) {
@@ -288,8 +356,8 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
if ((dup = allowed_commands)) {
argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
for (i = 0; i < argc; i++) {
for (i = 0; i < argc && argv[i]; i++) {
if (!strcasecmp(argv[i], command) || !strcasecmp(argv[i], "any")) {
ok = 1;
break;
@@ -310,17 +378,17 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
return ok ? TRUE : FALSE;
}
static abyss_bool http_directory_auth(TSession * r, char *domain_name)
static abyss_bool http_directory_auth(TSession *r, char *domain_name)
{
char *p;
char *x;
char z[256], t[80];
char user[512];
char *pass;
char *p = NULL;
char *x = NULL;
char z[256] = "", t[80] = "";
char user[512] = "" ;
char *pass = NULL;
const char *mypass1 = NULL, *mypass2 = NULL;
const char *box = NULL;
int at = 0;
char *dp;
char *dp = NULL;
abyss_bool rval = FALSE;
char *dup_domain = NULL;
@@ -372,13 +440,13 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
} else {
switch_snprintf(z, sizeof(z), "%s:%s", globals.user, globals.pass);
}
Base64Encode(z, t);
xmlrpc_base64Encode(z, t);
if (!strcmp(p, t)) {
goto authed;
}
}
if (!user_attributes(user, domain_name, &mypass1, &mypass2, &box, NULL)) {
goto fail;
}
@@ -396,7 +464,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
} else {
switch_snprintf(z, sizeof(z), "%s:%s", user, mypass1);
}
Base64Encode(z, t);
xmlrpc_base64Encode(z, t);
if (!strcmp(p, t)) {
goto authed;
@@ -408,7 +476,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
} else {
switch_snprintf(z, sizeof(z), "%s:%s", user, mypass2);
}
Base64Encode(z, t);
xmlrpc_base64Encode(z, t);
if (!strcmp(p, t)) {
goto authed;
@@ -421,7 +489,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
} else {
switch_snprintf(z, sizeof(z), "%s:%s", box, mypass1);
}
Base64Encode(z, t);
xmlrpc_base64Encode(z, t);
if (!strcmp(p, t)) {
goto authed;
@@ -434,7 +502,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
switch_snprintf(z, sizeof(z), "%s:%s", box, mypass2);
}
Base64Encode(z, t);
xmlrpc_base64Encode(z, t);
if (!strcmp(p, t)) {
goto authed;
@@ -536,19 +604,19 @@ abyss_bool auth_hook(TSession * r)
}
static abyss_bool HTTPWrite(TSession * s, char *buffer, uint32_t len)
static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len)
{
if (s->chunkedwrite && s->chunkedwritemode) {
char t[16];
if (ConnWrite(s->conn, t, sprintf(t, "%x" CRLF, len)))
if (ConnWrite(s->conn, buffer, len))
return ConnWrite(s->conn, CRLF, 2);
if (ConnWrite(s->connP, t, sprintf(t, "%x" CRLF, len)))
if (ConnWrite(s->connP, buffer, len))
return ConnWrite(s->connP, CRLF, 2);
return FALSE;
}
return ConnWrite(s->conn, buffer, len);
return ConnWrite(s->connP, buffer, len);
}
static abyss_bool HTTPWriteEnd(TSession * s)
@@ -559,7 +627,7 @@ static abyss_bool HTTPWriteEnd(TSession * s)
if (s->chunkedwrite) {
/* May be one day trailer dumping will be added */
s->chunkedwritemode = FALSE;
return ConnWrite(s->conn, "0" CRLF CRLF, 5);
return ConnWrite(s->connP, "0" CRLF CRLF, 5);
}
s->requestInfo.keepalive = FALSE;
@@ -568,47 +636,48 @@ static abyss_bool HTTPWriteEnd(TSession * s)
abyss_bool handler_hook(TSession * r)
{
//char *mime = "text/html";
char buf[80] = "HTTP/1.1 200 OK\n";
switch_stream_handle_t stream = { 0 };
char *command;
int i;
TTableItem *ti;
char *fs_user = NULL, *fs_domain = NULL;
char *path_info = NULL;
abyss_bool ret = TRUE;
int html = 0, text = 0, xml = 0;
int html = 0, text = 0, xml = 0, api = 0;
const char *api_str;
const char *uri = 0;
TRequestInfo *info = 0;
switch_event_t *evnt = 0; /* shortcut to stream.param_event */
if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) {
return FALSE;
}
stream.data = r;
stream.write_function = http_stream_write;
stream.raw_write_function = http_stream_raw_write;
if (!r || !r->requestInfo.uri) {
return FALSE;
}
if ((command = strstr(r->requestInfo.uri, "/api/"))) {
if ((command = strstr(uri, "/api/"))) {
command += 5;
} else if ((command = strstr(r->requestInfo.uri, "/webapi/"))) {
api++;
} else if ((command = strstr(uri, "/webapi/"))) {
command += 8;
html++;
} else if ((command = strstr(r->requestInfo.uri, "/txtapi/"))) {
} else if ((command = strstr(uri, "/txtapi/"))) {
command += 8;
text++;
} else if ((command = strstr(r->requestInfo.uri, "/xmlapi/"))) {
} else if ((command = strstr(uri, "/xmlapi/"))) {
command += 8;
xml++;
} else {
return FALSE;
return FALSE; /* 404 */
}
if ((path_info = strchr(command, '/'))) {
*path_info++ = '\0';
}
for (i = 0; i < r->response_headers.size; i++) {
ti = &r->response_headers.item[i];
for (i = 0; i < r->responseHeaderFields.size; i++) {
TTableItem *ti = &r->responseHeaderFields.item[i];
if (!strcasecmp(ti->name, "freeswitch-user")) {
fs_user = ti->value;
} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
@@ -616,63 +685,58 @@ abyss_bool handler_hook(TSession * r)
}
}
if (is_authorized(r, command)) {
goto auth;
if (!is_authorized(r, command)) {
ret = TRUE;
goto end;
}
ret = TRUE;
goto end;
auth:
/* auth: */
if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
const char *const content_length = RequestHeaderValue(r, "content-length");
evnt = stream.param_event;
if (html)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/html");
else if (text)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/plain");
else if (xml)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/xml");
if (fs_user)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
if (fs_domain)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
if (path_info)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-URI", r->requestInfo.uri);
if (r->requestInfo.query)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", r->requestInfo.query);
if (r->requestInfo.host)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-HOST", r->requestInfo.host);
if (r->requestInfo.from)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-FROM", r->requestInfo.from);
if (r->requestInfo.useragent)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", r->requestInfo.useragent);
if (r->requestInfo.referer)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REFERER", r->requestInfo.referer);
if (r->requestInfo.requestline)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", r->requestInfo.requestline);
if (r->requestInfo.user)
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER", r->requestInfo.user);
if (r->requestInfo.port)
switch_event_add_header(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->requestInfo.port);
if (r->requestInfo.query || content_length) {
if (html) {
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html");
} else if (text) {
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain");
} else if (xml) {
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml");
}
if (api) {
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api");
}
if (fs_user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);
if (info->host) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host);
if (info->from) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from);
if (info->useragent) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent);
if (info->referer) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer);
if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline);
if (info->user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user);
if (info->port) switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port);
{
char *q, *qd;
char *next;
char *query = (char *) r->requestInfo.query;
char *query = (char *) info->query;
char *name, *val;
char qbuf[8192] = "";
if (r->requestInfo.method == m_post && content_length) {
/* first finish reading from the socket if post method was used*/
if (info->method == m_post && content_length) {
int len = atoi(content_length);
int qlen = 0;
if (len > 0) {
int succeeded;
int succeeded = TRUE;
char *qp = qbuf;
char *readError;
do {
int blen = r->conn->buffersize - r->conn->bufferpos;
int blen = r->connP->buffersize - r->connP->bufferpos;
if ((qlen + blen) > len) {
blen = len - qlen;
@@ -684,75 +748,101 @@ abyss_bool handler_hook(TSession * r)
break;
}
memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen);
memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen);
qp += blen;
if (qlen >= len) {
break;
}
} while ((succeeded = ConnRead(r->conn, 2000)));
ConnRead(r->connP, 2000, NULL, NULL, &readError);
if (readError) {
succeeded = FALSE;
free(readError);
}
} while (succeeded);
query = qbuf;
}
}
/* parse query and add kv-pairs as event headers */
/* a kv pair starts with '&', '+' or \0 mark the end */
if (query) {
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);
qd = strdup(query);
switch_assert(qd != NULL);
q = qd;
next = q;
do {
char *p;
if ((next = strchr(next, '&'))) {
*next++ = '\0';
}
for (p = q; p && *p; p++) {
if (*p == '+') {
*p = ' ';
}
}
switch_url_decode(q);
name = q;
if ((val = strchr(name, '='))) {
*val++ = '\0';
switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, name, val);
}
q = next;
} while (q != NULL);
free(qd);
} else {
qd = strdup(uri);
}
switch_assert(qd != NULL);
q = qd;
next = q;
do {
char *p;
if (next = strchr(next, '&')) {
if (!query) {
/* pass kv pairs from uri to query */
/* "?" is absent in url so parse uri */
*((char *)uri + (next - q - 1)) = '\0';
query = next;
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next);
/* and strip uri */
/* the start of first kv pair marks the end of uri */
/* to prevent kv-pairs confusing fs api commands */
/* that have arguments separated by space */
}
*next++ = '\0';
}
for (p = q; p && *p; p++) {
if (*p == '+') {
*p = ' ';
}
}
/* hmmm, get method requests are already decoded ... */
switch_url_decode(q);
name = q;
if ((val = strchr(name, '='))) {
*val++ = '\0';
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val);
}
q = next;
} while (q != NULL);
free(qd);
}
}
//ResponseChunked(r);
//ResponseContentType(r, mime);
//ResponseWrite(r);
switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri);
HTTPWrite(r, buf, (uint32_t) strlen(buf));
/* We made it this far, always OK */
if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) {
return TRUE;
}
//HTTPWrite(r, "<pre>\n\n", 7);
ResponseAddField(r, "Connection", "close");
/* generation of the date field */
if (evnt)
{
ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT"));
}
else {
const char *dateValue;
DateToString(r->date, &dateValue);
if (dateValue) {
ResponseAddField(r, "Date", dateValue);
free(dateValue);
free((void *)dateValue);
}
}
/* Generation of the server field */
ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");
@@ -764,48 +854,45 @@ abyss_bool handler_hook(TSession * r)
ResponseAddField(r, "Content-Type", "text/xml");
}
for (i = 0; i < r->response_headers.size; i++) {
ti = &r->response_headers.item[i];
ConnWrite(r->conn, ti->name, (uint32_t) strlen(ti->name));
ConnWrite(r->conn, ": ", 2);
ConnWrite(r->conn, ti->value, (uint32_t) strlen(ti->value));
ConnWrite(r->conn, CRLF, 2);
for (i = 0; i < r->responseHeaderFields.size; i++) {
TTableItem *ti = &r->responseHeaderFields.item[i];
char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value);
if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) {
switch_safe_free(header);
return TRUE;
}
switch_safe_free(header);
}
switch_snprintf(buf, sizeof(buf), "Connection: close\r\n");
ConnWrite(r->conn, buf, (uint32_t) strlen(buf));
if (html || text || xml) {
ConnWrite(r->conn, "\r\n", 2);
/* send end http header */
if (html||text||xml) {
if (!ConnWrite(r->connP, CRLF, 2)) {
return TRUE;
}
}
else {
/* content-type and end of http header will be streamed by fs api or http_stream_write */
}
if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) {
command = "bgapi";
api_str = "unload mod_xml_rpc";
} else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
} else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) {
command = "bgapi";
api_str = "reload mod_xml_rpc";
} else {
api_str = r->requestInfo.query;
api_str = info->query;
}
if (switch_api_execute(command, api_str, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
ResponseStatus(r, 200);
r->responseStarted = TRUE;
//r->done = TRUE;
} else {
ResponseStatus(r, 404);
ResponseError(r);
}
/* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands */
//SocketClose(&(r->conn->socket));
/* execute actual fs api command */
/* fs api command will write to stream, calling http_stream_write / http_stream_raw_write */
/* switch_api_execute will stream INVALID COMMAND before it fails */
switch_api_execute(command, api_str, NULL, &stream);
HTTPWriteEnd(r);
//if (r->conn->channelP)
//ConnKill(r->conn);
//ChannelInterrupt(r->conn->channelP);
//ConnClose(r->conn);
//ChannelDestroy(r->conn->channelP);
r->responseStarted = TRUE;
ResponseStatus(r, 200); /* we don't want an assertion failure */
r->requestInfo.keepalive = 0;
end:
@@ -925,7 +1012,6 @@ static xmlrpc_value *freeswitch_man(xmlrpc_env * const envP, xmlrpc_value * cons
SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)
{
xmlrpc_registry *registryP;
xmlrpc_env env;
char logfile[512];
switch_hash_index_t *hi;
@@ -936,15 +1022,16 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)
xmlrpc_env_init(&env);
registryP = xmlrpc_registry_new(&env);
globals.registryP = xmlrpc_registry_new(&env);
xmlrpc_registry_add_method2(&env, registryP, "freeswitch.api", &freeswitch_api, NULL, NULL, NULL);
xmlrpc_registry_add_method2(&env, registryP, "freeswitch_api", &freeswitch_api, NULL, NULL, NULL);
xmlrpc_registry_add_method(&env, registryP, NULL, "freeswitch.management", &freeswitch_man, NULL);
xmlrpc_registry_add_method(&env, registryP, NULL, "freeswitch_management", &freeswitch_man, NULL);
/* TODO why twice and why add_method for freeswitch.api and add_method2 for freeswitch.management ? */
xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch.api", &freeswitch_api, NULL, NULL, NULL);
xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch_api", &freeswitch_api, NULL, NULL, NULL);
xmlrpc_registry_add_method(&env, globals.registryP, NULL, "freeswitch.management", &freeswitch_man, NULL);
xmlrpc_registry_add_method(&env, globals.registryP, NULL, "freeswitch_management", &freeswitch_man, NULL);
MIMETypeInit();
MIMETypeAdd("text/html", "html");
for (hi = switch_core_mime_index(); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if (var && val) {
@@ -955,38 +1042,52 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)
switch_snprintf(logfile, sizeof(logfile), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, "freeswitch_http.log");
ServerCreate(&globals.abyssServer, "XmlRpcServer", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, logfile);
xmlrpc_server_abyss_set_handler(&env, &globals.abyssServer, "/RPC2", registryP);
xmlrpc_server_abyss_set_handler(&env, &globals.abyssServer, "/RPC2", globals.registryP);
xmlrpc_env_clean(&env);
if (ServerInit(&globals.abyssServer) != TRUE) {
globals.running = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to start HTTP Port %d\n", globals.port);
xmlrpc_registry_free(globals.registryP);
MIMETypeTerm();
return SWITCH_STATUS_TERM;
}
ServerAddHandler(&globals.abyssServer, handler_hook);
ServerAddHandler(&globals.abyssServer, auth_hook);
ServerSetKeepaliveTimeout(&globals.abyssServer, 1);
ServerSetKeepaliveTimeout(&globals.abyssServer, 5);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]\n", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir);
ServerRun(&globals.abyssServer);
switch_yield(1000000);
globals.running = 0;
return SWITCH_STATUS_TERM;
}
/* upon module unload */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)
{
//globals.abyssServer.running = 0;
//shutdown(globals.abyssServer.listensock, 2);
/* this makes the worker thread (ServerRun) stop */
ServerTerminate(&globals.abyssServer);
do {
switch_yield(100000);
} while (globals.running);
ServerFree(&globals.abyssServer);
xmlrpc_registry_free(globals.registryP);
MIMETypeTerm();
switch_safe_free(globals.realm);
switch_safe_free(globals.user);
switch_safe_free(globals.pass);
switch_safe_free(globals.default_domain);
return SWITCH_STATUS_SUCCESS;
}
+2 -2
View File
@@ -2259,10 +2259,10 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
}
if (stream->param_event) {
if (cmd_used) {
if (cmd_used && *cmd_used) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used);
}
if (arg_used) {
if (arg_used && *arg_used) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used);
}
}
+21 -4
View File
@@ -972,7 +972,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_str_dynamic(char *s, switch_bool_t
}
}
/* parse the given xml string and return an switch_xml structure */
/* parse the given xml string and return a switch_xml structure */
SWITCH_DECLARE(switch_xml_t) switch_xml_parse_str(char *s, switch_size_t len)
{
switch_xml_root_t root = (switch_xml_root_t) switch_xml_new(NULL);
@@ -2455,7 +2455,7 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
*len += sprintf(*s + *len, "%s", XML_INDENT); /* indent */
}
}
*len += sprintf(*s + (*len), "</%s>\n", xml->name); /* close tag */
*len += sprintf(*s + (*len), "</%s>", xml->name); /* close tag */
}
while (txt[off] && off < xml->off)
@@ -2496,7 +2496,24 @@ SWITCH_DECLARE(char *) switch_xml_toxml(switch_xml_t xml, switch_bool_t prn_head
return r;
}
/* converts an switch_xml structure back to xml, returning a string of xml date that
SWITCH_DECLARE(char *) switch_xml_tohtml(switch_xml_t xml, switch_bool_t prn_header)
{
char *r, *s, *h;
switch_size_t rlen = 0;
switch_size_t len = SWITCH_XML_BUFSIZE;
switch_mutex_lock(XML_GEN_LOCK);
s = (char *) malloc(SWITCH_XML_BUFSIZE);
switch_assert(s);
h = (char *) malloc(SWITCH_XML_BUFSIZE);
switch_assert(h);
r = switch_xml_toxml_buf(xml, s, SWITCH_XML_BUFSIZE, 0, prn_header);
h = switch_xml_ampencode(r, 0, &h, &rlen, &len, 1);
switch_safe_free(r);
switch_mutex_unlock(XML_GEN_LOCK);
return h;
}
/* converts a switch_xml structure back to xml, returning a string of xml data that
must be freed */
SWITCH_DECLARE(char *) switch_xml_toxml_buf(switch_xml_t xml, char *buf, switch_size_t buflen, switch_size_t offset, switch_bool_t prn_header)
{
@@ -2684,7 +2701,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_new(const char *name)
return &root->xml;
}
/* inserts an existing tag into an switch_xml structure */
/* inserts an existing tag into a switch_xml structure */
SWITCH_DECLARE(switch_xml_t) switch_xml_insert(switch_xml_t xml, switch_xml_t dest, switch_size_t off)
{
switch_xml_t cur, prev, head;