Merge pull request #2911 from hax0kartik/dl-curl
Dynamically load libcurl, libvlc and libvnc
This commit is contained in:
commit
4b53c7660e
|
@ -324,7 +324,7 @@ if(NOT ZM_NO_CURL)
|
||||||
find_package(CURL)
|
find_package(CURL)
|
||||||
if(CURL_FOUND)
|
if(CURL_FOUND)
|
||||||
set(HAVE_LIBCURL 1)
|
set(HAVE_LIBCURL 1)
|
||||||
list(APPEND ZM_BIN_LIBS ${CURL_LIBRARIES})
|
#list(APPEND ZM_BIN_LIBS ${CURL_LIBRARIES})
|
||||||
include_directories(${CURL_INCLUDE_DIRS})
|
include_directories(${CURL_INCLUDE_DIRS})
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS})
|
||||||
check_include_file("curl/curl.h" HAVE_CURL_CURL_H)
|
check_include_file("curl/curl.h" HAVE_CURL_CURL_H)
|
||||||
|
@ -363,8 +363,9 @@ else(LIBJWT_FOUND)
|
||||||
endif(LIBJWT_FOUND)
|
endif(LIBJWT_FOUND)
|
||||||
|
|
||||||
# gnutls (using find_library and find_path)
|
# gnutls (using find_library and find_path)
|
||||||
find_library(GNUTLS_LIBRARIES gnutls)
|
if(HAVE_LIBJWT)
|
||||||
if(GNUTLS_LIBRARIES)
|
find_library(GNUTLS_LIBRARIES gnutls)
|
||||||
|
if(GNUTLS_LIBRARIES)
|
||||||
set(HAVE_LIBGNUTLS 1)
|
set(HAVE_LIBGNUTLS 1)
|
||||||
list(APPEND ZM_BIN_LIBS "${GNUTLS_LIBRARIES}")
|
list(APPEND ZM_BIN_LIBS "${GNUTLS_LIBRARIES}")
|
||||||
find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h)
|
find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h)
|
||||||
|
@ -375,9 +376,10 @@ if(GNUTLS_LIBRARIES)
|
||||||
mark_as_advanced(FORCE GNUTLS_LIBRARIES GNUTLS_INCLUDE_DIR)
|
mark_as_advanced(FORCE GNUTLS_LIBRARIES GNUTLS_INCLUDE_DIR)
|
||||||
check_include_file("gnutls/gnutls.h" HAVE_GNUTLS_GNUTLS_H)
|
check_include_file("gnutls/gnutls.h" HAVE_GNUTLS_GNUTLS_H)
|
||||||
set(optlibsfound "${optlibsfound} GnuTLS")
|
set(optlibsfound "${optlibsfound} GnuTLS")
|
||||||
else(GNUTLS_LIBRARIES)
|
else(GNUTLS_LIBRARIES)
|
||||||
set(optlibsnotfound "${optlibsnotfound} GnuTLS")
|
set(optlibsnotfound "${optlibsnotfound} GnuTLS")
|
||||||
endif(GNUTLS_LIBRARIES)
|
endif(GNUTLS_LIBRARIES)
|
||||||
|
endif(HAVE_LIBJWT)
|
||||||
|
|
||||||
# OpenSSL
|
# OpenSSL
|
||||||
if(NOT HAVE_LIBGNUTLS OR NOT HAVE_LIBJWT)
|
if(NOT HAVE_LIBGNUTLS OR NOT HAVE_LIBJWT)
|
||||||
|
@ -665,7 +667,7 @@ if(NOT ZM_NO_LIBVLC)
|
||||||
find_library(LIBVLC_LIBRARIES vlc)
|
find_library(LIBVLC_LIBRARIES vlc)
|
||||||
if(LIBVLC_LIBRARIES)
|
if(LIBVLC_LIBRARIES)
|
||||||
set(HAVE_LIBVLC 1)
|
set(HAVE_LIBVLC 1)
|
||||||
list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
|
#list(APPEND ZM_BIN_LIBS "${LIBVLC_LIBRARIES}")
|
||||||
find_path(LIBVLC_INCLUDE_DIR "vlc/vlc.h")
|
find_path(LIBVLC_INCLUDE_DIR "vlc/vlc.h")
|
||||||
if(LIBVLC_INCLUDE_DIR)
|
if(LIBVLC_INCLUDE_DIR)
|
||||||
include_directories("${LIBVLC_INCLUDE_DIR}")
|
include_directories("${LIBVLC_INCLUDE_DIR}")
|
||||||
|
@ -684,7 +686,7 @@ if(NOT ZM_NO_LIBVNC)
|
||||||
find_library(LIBVNC_LIBRARIES vncclient)
|
find_library(LIBVNC_LIBRARIES vncclient)
|
||||||
if(LIBVNC_LIBRARIES)
|
if(LIBVNC_LIBRARIES)
|
||||||
set(HAVE_LIBVNC 1)
|
set(HAVE_LIBVNC 1)
|
||||||
list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}")
|
#list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}")
|
||||||
find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h")
|
find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h")
|
||||||
if(LIBVNC_INCLUDE_DIR)
|
if(LIBVNC_INCLUDE_DIR)
|
||||||
include_directories("${LIBVNC_INCLUDE_DIR}")
|
include_directories("${LIBVNC_INCLUDE_DIR}")
|
||||||
|
@ -773,9 +775,9 @@ if(HAVE_GNUTLS_GNUTLS_H)
|
||||||
HAVE_DECL_GNUTLS_FINGERPRINT)
|
HAVE_DECL_GNUTLS_FINGERPRINT)
|
||||||
endif(HAVE_GNUTLS_GNUTLS_H)
|
endif(HAVE_GNUTLS_GNUTLS_H)
|
||||||
|
|
||||||
if(HAVE_MD5_OPENSSL)
|
if(NOT HAVE_DECL_GNUTLS_FINGERPRINT AND HAVE_MD5_OPENSSL)
|
||||||
set(HAVE_DECL_MD5 1)
|
set(HAVE_DECL_MD5 1)
|
||||||
endif(HAVE_MD5_OPENSSL)
|
endif(NOT HAVE_DECL_GNUTLS_FINGERPRINT AND HAVE_MD5_OPENSSL)
|
||||||
|
|
||||||
if((NOT HAVE_MD5_OPENSSL) AND (NOT HAVE_DECL_GNUTLS_FINGERPRINT))
|
if((NOT HAVE_MD5_OPENSSL) AND (NOT HAVE_DECL_GNUTLS_FINGERPRINT))
|
||||||
message(AUTHOR_WARNING
|
message(AUTHOR_WARNING
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
#include "zm.h"
|
#include "zm.h"
|
||||||
|
|
||||||
#include "zm_curl_camera.h"
|
#include "zm_curl_camera.h"
|
||||||
|
@ -25,6 +26,18 @@
|
||||||
|
|
||||||
#if HAVE_LIBCURL
|
#if HAVE_LIBCURL
|
||||||
|
|
||||||
|
/* Func ptrs for libcurl functions */
|
||||||
|
static void *curl_lib = nullptr;
|
||||||
|
static CURLcode (*curl_global_init_f)(long) = nullptr;
|
||||||
|
static void (*curl_global_cleanup_f)(void) = nullptr;
|
||||||
|
static const char* (*curl_easy_strerror_f)(CURLcode) = nullptr;
|
||||||
|
static char* (*curl_version_f)(void) = nullptr;
|
||||||
|
static CURL* (*curl_easy_init_f)(void) = nullptr;
|
||||||
|
static CURLcode (*curl_easy_getinfo_f)(CURL* , CURLINFO, ...) = nullptr;
|
||||||
|
static CURLcode (*curl_easy_perform_f)(CURL*) = nullptr;
|
||||||
|
static CURLcode (*curl_easy_setopt_f)(CURL*, CURLoption, ...) = nullptr;
|
||||||
|
static void (*curl_easy_cleanup_f)(CURL*) = nullptr;
|
||||||
|
|
||||||
#define CURL_MAXRETRY 5
|
#define CURL_MAXRETRY 5
|
||||||
#define CURL_BUFFER_INITIAL_SIZE 65536
|
#define CURL_BUFFER_INITIAL_SIZE 65536
|
||||||
|
|
||||||
|
@ -33,6 +46,31 @@ const char* content_type_match = "Content-Type:";
|
||||||
size_t content_length_match_len;
|
size_t content_length_match_len;
|
||||||
size_t content_type_match_len;
|
size_t content_type_match_len;
|
||||||
|
|
||||||
|
void bind_libcurl_symbols() {
|
||||||
|
|
||||||
|
if(curl_lib)
|
||||||
|
return;
|
||||||
|
|
||||||
|
curl_lib = dlopen("libcurl.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if(!curl_lib)
|
||||||
|
curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if (!curl_lib) {
|
||||||
|
Error("Could not load libcurl: %s", dlerror());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load up all required symbols here
|
||||||
|
*(void**) (&curl_global_init_f) = dlsym(curl_lib, "curl_global_init");
|
||||||
|
*(void**) (&curl_global_cleanup_f) = dlsym(curl_lib, "curl_global_cleanup");
|
||||||
|
*(void**) (&curl_easy_strerror_f) = dlsym(curl_lib, "curl_easy_strerror");
|
||||||
|
*(void**) (&curl_version_f) = dlsym(curl_lib, "curl_version");
|
||||||
|
*(void**) (&curl_easy_init_f) = dlsym(curl_lib, "curl_easy_init");
|
||||||
|
*(void**) (&curl_easy_getinfo_f) = dlsym(curl_lib, "curl_easy_getinfo");
|
||||||
|
*(void**) (&curl_easy_perform_f) = dlsym(curl_lib, "curl_easy_perform");
|
||||||
|
*(void**) (&curl_easy_setopt_f) = dlsym(curl_lib, "curl_easy_setopt");
|
||||||
|
*(void**) (&curl_easy_cleanup_f) = dlsym(curl_lib, "curl_easy_cleanup");
|
||||||
|
}
|
||||||
|
|
||||||
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, unsigned int p_width, unsigned int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, unsigned int p_width, unsigned int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||||
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||||
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
|
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
|
||||||
|
@ -56,34 +94,41 @@ void cURLCamera::Initialise() {
|
||||||
|
|
||||||
databuffer.expand(CURL_BUFFER_INITIAL_SIZE);
|
databuffer.expand(CURL_BUFFER_INITIAL_SIZE);
|
||||||
|
|
||||||
|
bind_libcurl_symbols();
|
||||||
/* cURL initialization */
|
/* cURL initialization */
|
||||||
CURLcode cRet = curl_global_init(CURL_GLOBAL_ALL);
|
CURLcode cRet = (*curl_global_init_f)(CURL_GLOBAL_ALL);
|
||||||
if(cRet != CURLE_OK) {
|
if(cRet != CURLE_OK) {
|
||||||
Fatal("libcurl initialization failed: ", curl_easy_strerror(cRet));
|
Error("libcurl initialization failed: ", (*curl_easy_strerror_f)(cRet));
|
||||||
|
dlclose(curl_lib);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(2,"libcurl version: %s",curl_version());
|
Debug(2,"libcurl version: %s", (*curl_version_f)());
|
||||||
|
|
||||||
/* Create the shared data mutex */
|
/* Create the shared data mutex */
|
||||||
int nRet = pthread_mutex_init(&shareddata_mutex, NULL);
|
int nRet = pthread_mutex_init(&shareddata_mutex, NULL);
|
||||||
if(nRet != 0) {
|
if(nRet != 0) {
|
||||||
Fatal("Shared data mutex creation failed: %s",strerror(nRet));
|
Error("Shared data mutex creation failed: %s",strerror(nRet));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/* Create the data available condition variable */
|
/* Create the data available condition variable */
|
||||||
nRet = pthread_cond_init(&data_available_cond, NULL);
|
nRet = pthread_cond_init(&data_available_cond, NULL);
|
||||||
if(nRet != 0) {
|
if(nRet != 0) {
|
||||||
Fatal("Data available condition variable creation failed: %s",strerror(nRet));
|
Error("Data available condition variable creation failed: %s",strerror(nRet));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/* Create the request complete condition variable */
|
/* Create the request complete condition variable */
|
||||||
nRet = pthread_cond_init(&request_complete_cond, NULL);
|
nRet = pthread_cond_init(&request_complete_cond, NULL);
|
||||||
if(nRet != 0) {
|
if(nRet != 0) {
|
||||||
Fatal("Request complete condition variable creation failed: %s",strerror(nRet));
|
Error("Request complete condition variable creation failed: %s",strerror(nRet));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the thread */
|
/* Create the thread */
|
||||||
nRet = pthread_create(&thread, NULL, thread_func_dispatcher, this);
|
nRet = pthread_create(&thread, NULL, thread_func_dispatcher, this);
|
||||||
if(nRet != 0) {
|
if(nRet != 0) {
|
||||||
Fatal("Thread creation failed: %s",strerror(nRet));
|
Error("Thread creation failed: %s",strerror(nRet));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +147,10 @@ void cURLCamera::Terminate() {
|
||||||
pthread_mutex_destroy(&shareddata_mutex);
|
pthread_mutex_destroy(&shareddata_mutex);
|
||||||
|
|
||||||
/* cURL cleanup */
|
/* cURL cleanup */
|
||||||
curl_global_cleanup();
|
(*curl_global_cleanup_f)();
|
||||||
|
|
||||||
|
if(curl_lib)
|
||||||
|
dlclose(curl_lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cURLCamera::PrimeCapture() {
|
int cURLCamera::PrimeCapture() {
|
||||||
|
@ -287,7 +334,8 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Failed to match content-type */
|
/* Failed to match content-type */
|
||||||
Fatal("Unable to match Content-Type. Check URL, username and password");
|
Error("Unable to match Content-Type. Check URL, username and password");
|
||||||
|
return -21;
|
||||||
} /* mode */
|
} /* mode */
|
||||||
|
|
||||||
} /* frameComplete loop */
|
} /* frameComplete loop */
|
||||||
|
@ -376,60 +424,88 @@ void* cURLCamera::thread_func() {
|
||||||
long tRet;
|
long tRet;
|
||||||
double dSize;
|
double dSize;
|
||||||
|
|
||||||
c = curl_easy_init();
|
c = (*curl_easy_init_f)();
|
||||||
if(c == NULL) {
|
if(c == NULL) {
|
||||||
Fatal("Failed getting easy handle from libcurl");
|
dlclose(curl_lib);
|
||||||
|
Error("Failed getting easy handle from libcurl");
|
||||||
|
tRet = -51;
|
||||||
|
return (void*)tRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode cRet;
|
CURLcode cRet;
|
||||||
/* Set URL */
|
/* Set URL */
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_URL, mPath.c_str());
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_URL, mPath.c_str());
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK) {
|
||||||
Fatal("Failed setting libcurl URL: %s", curl_easy_strerror(cRet));
|
Error("Failed setting libcurl URL: %s", *(curl_easy_strerror_f)(cRet));
|
||||||
|
tRet = -52;
|
||||||
|
return (void*)tRet;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header callback */
|
/* Header callback */
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher);
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher);
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK) {
|
||||||
Fatal("Failed setting libcurl header callback function: %s", curl_easy_strerror(cRet));
|
Error("Failed setting libcurl header callback function: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_HEADERDATA, this);
|
tRet = -53;
|
||||||
if(cRet != CURLE_OK)
|
return (void*)tRet;
|
||||||
Fatal("Failed setting libcurl header callback object: %s", curl_easy_strerror(cRet));
|
}
|
||||||
|
|
||||||
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_HEADERDATA, this);
|
||||||
|
if(cRet != CURLE_OK) {
|
||||||
|
Error("Failed setting libcurl header callback object: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
|
tRet = -54;
|
||||||
|
return (void*)tRet;
|
||||||
|
}
|
||||||
/* Data callback */
|
/* Data callback */
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher);
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher);
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK) {
|
||||||
Fatal("Failed setting libcurl data callback function: %s", curl_easy_strerror(cRet));
|
Error("Failed setting libcurl data callback function: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_WRITEDATA, this);
|
tRet = -55;
|
||||||
if(cRet != CURLE_OK)
|
return (void*)tRet;
|
||||||
Fatal("Failed setting libcurl data callback object: %s", curl_easy_strerror(cRet));
|
}
|
||||||
|
|
||||||
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_WRITEDATA, this);
|
||||||
|
if(cRet != CURLE_OK) {
|
||||||
|
Error("Failed setting libcurl data callback object: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
|
tRet = -56;
|
||||||
|
return (void*)tRet;
|
||||||
|
}
|
||||||
/* Progress callback */
|
/* Progress callback */
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0);
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_NOPROGRESS, 0);
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK) {
|
||||||
Fatal("Failed enabling libcurl progress callback function: %s", curl_easy_strerror(cRet));
|
Error("Failed enabling libcurl progress callback function: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher);
|
tRet = -57;
|
||||||
if(cRet != CURLE_OK)
|
return (void*)tRet;
|
||||||
Fatal("Failed setting libcurl progress callback function: %s", curl_easy_strerror(cRet));
|
}
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_PROGRESSDATA, this);
|
|
||||||
if(cRet != CURLE_OK)
|
|
||||||
Fatal("Failed setting libcurl progress callback object: %s", curl_easy_strerror(cRet));
|
|
||||||
|
|
||||||
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher);
|
||||||
|
if(cRet != CURLE_OK) {
|
||||||
|
Error("Failed setting libcurl progress callback function: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
|
tRet = -58;
|
||||||
|
return (void*)tRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_PROGRESSDATA, this);
|
||||||
|
if(cRet != CURLE_OK) {
|
||||||
|
Error("Failed setting libcurl progress callback object: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
|
tRet = -59;
|
||||||
|
return (void*)tRet;
|
||||||
|
}
|
||||||
/* Set username and password */
|
/* Set username and password */
|
||||||
if(!mUser.empty()) {
|
if(!mUser.empty()) {
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_USERNAME, mUser.c_str());
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_USERNAME, mUser.c_str());
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK)
|
||||||
Error("Failed setting username: %s", curl_easy_strerror(cRet));
|
Error("Failed setting username: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
}
|
}
|
||||||
if(!mPass.empty()) {
|
if(!mPass.empty()) {
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_PASSWORD, mPass.c_str());
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_PASSWORD, mPass.c_str());
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK)
|
||||||
Error("Failed setting password: %s", curl_easy_strerror(cRet));
|
Error("Failed setting password: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Authenication preference */
|
/* Authenication preference */
|
||||||
cRet = curl_easy_setopt(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
cRet = (*curl_easy_setopt_f)(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||||
if(cRet != CURLE_OK)
|
if(cRet != CURLE_OK)
|
||||||
Warning("Failed setting libcurl acceptable http authenication methods: %s", curl_easy_strerror(cRet));
|
Warning("Failed setting libcurl acceptable http authenication methods: %s", (*curl_easy_strerror_f)(cRet));
|
||||||
|
|
||||||
|
|
||||||
/* Work loop */
|
/* Work loop */
|
||||||
|
@ -437,14 +513,14 @@ void* cURLCamera::thread_func() {
|
||||||
tRet = 0;
|
tRet = 0;
|
||||||
while(!bTerminate) {
|
while(!bTerminate) {
|
||||||
/* Do the work */
|
/* Do the work */
|
||||||
cRet = curl_easy_perform(c);
|
cRet = (*curl_easy_perform_f)(c);
|
||||||
|
|
||||||
if(mode == MODE_SINGLE) {
|
if(mode == MODE_SINGLE) {
|
||||||
if(cRet != CURLE_OK) {
|
if(cRet != CURLE_OK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Attempt to get the size of the file */
|
/* Attempt to get the size of the file */
|
||||||
cRet = curl_easy_getinfo(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize);
|
cRet = (*curl_easy_getinfo_f)(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize);
|
||||||
if(cRet != CURLE_OK) {
|
if(cRet != CURLE_OK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -454,12 +530,16 @@ void* cURLCamera::thread_func() {
|
||||||
if(dSize > 0) {
|
if(dSize > 0) {
|
||||||
single_offsets.push_back(dSize);
|
single_offsets.push_back(dSize);
|
||||||
} else {
|
} else {
|
||||||
Fatal("Unable to get the size of the image");
|
Error("Unable to get the size of the image");
|
||||||
|
tRet = -60;
|
||||||
|
return (void*)tRet;
|
||||||
}
|
}
|
||||||
/* Signal the request complete condition variable */
|
/* Signal the request complete condition variable */
|
||||||
tRet = pthread_cond_signal(&request_complete_cond);
|
tRet = pthread_cond_signal(&request_complete_cond);
|
||||||
if(tRet != 0) {
|
if(tRet != 0) {
|
||||||
Error("Failed signaling request completed condition variable: %s",strerror(tRet));
|
Error("Failed signaling request completed condition variable: %s",strerror(tRet));
|
||||||
|
tRet = -61;
|
||||||
|
return (void*)tRet;
|
||||||
}
|
}
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
unlock();
|
unlock();
|
||||||
|
@ -475,7 +555,7 @@ void* cURLCamera::thread_func() {
|
||||||
break;
|
break;
|
||||||
} else if (cRet != CURLE_OK) {
|
} else if (cRet != CURLE_OK) {
|
||||||
/* Some error */
|
/* Some error */
|
||||||
Error("cURL Request failed: %s",curl_easy_strerror(cRet));
|
Error("cURL Request failed: %s",(*curl_easy_strerror_f)(cRet));
|
||||||
if(attempt < CURL_MAXRETRY) {
|
if(attempt < CURL_MAXRETRY) {
|
||||||
Error("Retrying.. Attempt %d of %d",attempt,CURL_MAXRETRY);
|
Error("Retrying.. Attempt %d of %d",attempt,CURL_MAXRETRY);
|
||||||
/* Do a reset */
|
/* Do a reset */
|
||||||
|
@ -491,7 +571,7 @@ void* cURLCamera::thread_func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
curl_easy_cleanup(c);
|
(*curl_easy_cleanup_f)(c);
|
||||||
c = NULL;
|
c = NULL;
|
||||||
|
|
||||||
return (void*)tRet;
|
return (void*)tRet;
|
||||||
|
|
|
@ -17,12 +17,51 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
#include "zm.h"
|
#include "zm.h"
|
||||||
#include "zm_signal.h"
|
#include "zm_signal.h"
|
||||||
#include "zm_libvlc_camera.h"
|
#include "zm_libvlc_camera.h"
|
||||||
|
|
||||||
#if HAVE_LIBVLC
|
#if HAVE_LIBVLC
|
||||||
|
static void *libvlc_lib = nullptr;
|
||||||
|
static void (*libvlc_media_player_release_f)(libvlc_media_player_t* ) = nullptr;
|
||||||
|
static void (*libvlc_media_release_f)(libvlc_media_t* ) = nullptr;
|
||||||
|
static void (*libvlc_release_f)(libvlc_instance_t* ) = nullptr;
|
||||||
|
static void (*libvlc_media_player_stop_f)(libvlc_media_player_t* ) = nullptr;
|
||||||
|
static libvlc_instance_t* (*libvlc_new_f)(int, const char* const *) = nullptr;
|
||||||
|
static void (*libvlc_log_set_f)(libvlc_instance_t*, libvlc_log_cb, void *) = nullptr;
|
||||||
|
static libvlc_media_t* (*libvlc_media_new_location_f)(libvlc_instance_t*, const char*) = nullptr;
|
||||||
|
static libvlc_media_player_t* (*libvlc_media_player_new_from_media_f)(libvlc_media_t*) = nullptr;
|
||||||
|
static void (*libvlc_video_set_format_f)(libvlc_media_player_t*, const char*, unsigned, unsigned, unsigned) = nullptr;
|
||||||
|
static void (*libvlc_video_set_callbacks_f)(libvlc_media_player_t*, libvlc_video_lock_cb, libvlc_video_unlock_cb, libvlc_video_display_cb, void*) = nullptr;
|
||||||
|
static int (*libvlc_media_player_play_f)(libvlc_media_player_t *) = nullptr;
|
||||||
|
static const char* (*libvlc_errmsg_f)(void) = nullptr;
|
||||||
|
static const char* (*libvlc_get_version_f)(void) = nullptr;
|
||||||
|
|
||||||
|
void bind_libvlc_symbols() {
|
||||||
|
if(libvlc_lib != nullptr) // Safe-check
|
||||||
|
return;
|
||||||
|
|
||||||
|
libvlc_lib = dlopen("libvlc.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if(!libvlc_lib){
|
||||||
|
Error("Error loading libvlc: %s", dlerror());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void**) (&libvlc_media_player_release_f) = dlsym(libvlc_lib, "libvlc_media_player_release");
|
||||||
|
*(void**) (&libvlc_media_release_f) = dlsym(libvlc_lib, "libvlc_media_release");
|
||||||
|
*(void**) (&libvlc_release_f) = dlsym(libvlc_lib, "libvlc_release");
|
||||||
|
*(void**) (&libvlc_media_player_stop_f) = dlsym(libvlc_lib, "libvlc_media_player_stop");
|
||||||
|
*(void**) (&libvlc_new_f) = dlsym(libvlc_lib, "libvlc_new");
|
||||||
|
*(void**) (&libvlc_log_set_f) = dlsym(libvlc_lib, "libvlc_log_set");
|
||||||
|
*(void**) (&libvlc_media_new_location_f) = dlsym(libvlc_lib, "libvlc_media_new_location");
|
||||||
|
*(void**) (&libvlc_media_player_new_from_media_f) = dlsym(libvlc_lib, "libvlc_media_player_new_from_media");
|
||||||
|
*(void**) (&libvlc_video_set_format_f) = dlsym(libvlc_lib, "libvlc_video_set_format");
|
||||||
|
*(void**) (&libvlc_video_set_callbacks_f) = dlsym(libvlc_lib, "libvlc_video_set_callbacks");
|
||||||
|
*(void**) (&libvlc_media_player_play_f) = dlsym(libvlc_lib, "libvlc_media_player_play");
|
||||||
|
*(void**) (&libvlc_errmsg_f) = dlsym(libvlc_lib, "libvlc_errmsg");
|
||||||
|
*(void**) (&libvlc_get_version_f) = dlsym(libvlc_lib, "libvlc_get_version");
|
||||||
|
}
|
||||||
// Do all the buffer checking work here to avoid unnecessary locking
|
// Do all the buffer checking work here to avoid unnecessary locking
|
||||||
void* LibvlcLockBuffer(void* opaque, void** planes) {
|
void* LibvlcLockBuffer(void* opaque, void** planes) {
|
||||||
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
|
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
|
||||||
|
@ -125,15 +164,15 @@ LibvlcCamera::~LibvlcCamera() {
|
||||||
Terminate();
|
Terminate();
|
||||||
}
|
}
|
||||||
if ( mLibvlcMediaPlayer != NULL ) {
|
if ( mLibvlcMediaPlayer != NULL ) {
|
||||||
libvlc_media_player_release(mLibvlcMediaPlayer);
|
(*libvlc_media_player_release_f)(mLibvlcMediaPlayer);
|
||||||
mLibvlcMediaPlayer = NULL;
|
mLibvlcMediaPlayer = NULL;
|
||||||
}
|
}
|
||||||
if ( mLibvlcMedia != NULL ) {
|
if ( mLibvlcMedia != NULL ) {
|
||||||
libvlc_media_release(mLibvlcMedia);
|
(*libvlc_media_release_f)(mLibvlcMedia);
|
||||||
mLibvlcMedia = NULL;
|
mLibvlcMedia = NULL;
|
||||||
}
|
}
|
||||||
if ( mLibvlcInstance != NULL ) {
|
if ( mLibvlcInstance != NULL ) {
|
||||||
libvlc_release(mLibvlcInstance);
|
(*libvlc_release_f)(mLibvlcInstance);
|
||||||
mLibvlcInstance = NULL;
|
mLibvlcInstance = NULL;
|
||||||
}
|
}
|
||||||
if ( mOptArgV != NULL ) {
|
if ( mOptArgV != NULL ) {
|
||||||
|
@ -142,14 +181,16 @@ LibvlcCamera::~LibvlcCamera() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibvlcCamera::Initialise() {
|
void LibvlcCamera::Initialise() {
|
||||||
|
bind_libvlc_symbols();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibvlcCamera::Terminate() {
|
void LibvlcCamera::Terminate() {
|
||||||
libvlc_media_player_stop(mLibvlcMediaPlayer);
|
(*libvlc_media_player_stop_f)(mLibvlcMediaPlayer);
|
||||||
if ( mLibvlcData.buffer ) {
|
if ( mLibvlcData.buffer ) {
|
||||||
zm_freealigned(mLibvlcData.buffer);
|
zm_freealigned(mLibvlcData.buffer);
|
||||||
mLibvlcData.buffer = NULL;
|
mLibvlcData.buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mLibvlcData.prevBuffer ) {
|
if ( mLibvlcData.prevBuffer ) {
|
||||||
zm_freealigned(mLibvlcData.prevBuffer);
|
zm_freealigned(mLibvlcData.prevBuffer);
|
||||||
mLibvlcData.prevBuffer = NULL;
|
mLibvlcData.prevBuffer = NULL;
|
||||||
|
@ -158,6 +199,7 @@ void LibvlcCamera::Terminate() {
|
||||||
|
|
||||||
int LibvlcCamera::PrimeCapture() {
|
int LibvlcCamera::PrimeCapture() {
|
||||||
Info("Priming capture from %s", mPath.c_str());
|
Info("Priming capture from %s", mPath.c_str());
|
||||||
|
Info("Libvlc Version %s", (*libvlc_get_version_f)());
|
||||||
|
|
||||||
StringVector opVect = split(Options(), ",");
|
StringVector opVect = split(Options(), ",");
|
||||||
|
|
||||||
|
@ -181,28 +223,28 @@ int LibvlcCamera::PrimeCapture() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mLibvlcInstance = libvlc_new(opVect.size(), (const char* const*)mOptArgV);
|
mLibvlcInstance = (*libvlc_new_f)(opVect.size(), (const char* const*)mOptArgV);
|
||||||
if ( mLibvlcInstance == NULL ) {
|
if ( mLibvlcInstance == NULL ) {
|
||||||
Error("Unable to create libvlc instance due to: %s", libvlc_errmsg());
|
Error("Unable to create libvlc instance due to: %s", (*libvlc_errmsg_f)());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
libvlc_log_set(mLibvlcInstance, LibvlcCamera::log_callback, NULL);
|
(*libvlc_log_set_f)(mLibvlcInstance, LibvlcCamera::log_callback, NULL);
|
||||||
|
|
||||||
|
|
||||||
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
|
mLibvlcMedia = (*libvlc_media_new_location_f)(mLibvlcInstance, mPath.c_str());
|
||||||
if ( mLibvlcMedia == NULL ) {
|
if ( mLibvlcMedia == NULL ) {
|
||||||
Error("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg());
|
Error("Unable to open input %s due to: %s", mPath.c_str(), (*libvlc_errmsg_f)());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia);
|
mLibvlcMediaPlayer = (*libvlc_media_player_new_from_media_f)(mLibvlcMedia);
|
||||||
if ( mLibvlcMediaPlayer == NULL ) {
|
if ( mLibvlcMediaPlayer == NULL ) {
|
||||||
Error("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg());
|
Error("Unable to create player for %s due to: %s", mPath.c_str(), (*libvlc_errmsg_f)());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
|
(*libvlc_video_set_format_f)(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
|
||||||
libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
|
(*libvlc_video_set_callbacks_f)(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
|
||||||
|
|
||||||
mLibvlcData.bufferSize = width * height * mBpp;
|
mLibvlcData.bufferSize = width * height * mBpp;
|
||||||
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
|
// Libvlc wants 32 byte alignment for images (should in theory do this for all image lines)
|
||||||
|
@ -211,7 +253,7 @@ int LibvlcCamera::PrimeCapture() {
|
||||||
|
|
||||||
mLibvlcData.newImage.setValueImmediate(false);
|
mLibvlcData.newImage.setValueImmediate(false);
|
||||||
|
|
||||||
libvlc_media_player_play(mLibvlcMediaPlayer);
|
(*libvlc_media_player_play_f)(mLibvlcMediaPlayer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <dlfcn.h>
|
||||||
#include "zm.h"
|
#include "zm.h"
|
||||||
#include "zm_signal.h"
|
#include "zm_signal.h"
|
||||||
#include "zm_libvnc_camera.h"
|
#include "zm_libvnc_camera.h"
|
||||||
|
@ -8,14 +9,41 @@
|
||||||
static int TAG_0;
|
static int TAG_0;
|
||||||
static int TAG_1;
|
static int TAG_1;
|
||||||
static int TAG_2;
|
static int TAG_2;
|
||||||
|
static void *libvnc_lib = nullptr;
|
||||||
|
static void *(*rfbClientGetClientData_f)(rfbClient*, void*) = nullptr;
|
||||||
|
static rfbClient *(*rfbGetClient_f)(int, int, int) = nullptr;
|
||||||
|
static void (*rfbClientSetClientData_f)(rfbClient*, void*, void*) = nullptr;
|
||||||
|
static rfbBool (*rfbInitClient_f)(rfbClient*, int*, char**) = nullptr;
|
||||||
|
static void (*rfbClientCleanup_f)(rfbClient*) = nullptr;
|
||||||
|
static int (*WaitForMessage_f)(rfbClient*, unsigned int) = nullptr;
|
||||||
|
static rfbBool (*HandleRFBServerMessage_f)(rfbClient*) = nullptr;
|
||||||
|
|
||||||
|
void bind_libvnc_symbols() {
|
||||||
|
if(libvnc_lib != nullptr) // Safe-check
|
||||||
|
return;
|
||||||
|
|
||||||
|
libvnc_lib = dlopen("libvncclient.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if(!libvnc_lib){
|
||||||
|
Error("Error loading libvlc: %s", dlerror());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void**) (&rfbClientGetClientData_f) = dlsym(libvnc_lib, "rfbClientGetClientData");
|
||||||
|
*(void**) (&rfbGetClient_f) = dlsym(libvnc_lib, "rfbGetClient");
|
||||||
|
*(void**) (&rfbClientSetClientData_f) = dlsym(libvnc_lib, "rfbClientSetClientData");
|
||||||
|
*(void**) (&rfbInitClient_f) = dlsym(libvnc_lib, "rfbInitClient");
|
||||||
|
*(void**) (&rfbClientCleanup_f) = dlsym(libvnc_lib, "rfbClientCleanup");
|
||||||
|
*(void**) (&WaitForMessage_f) = dlsym(libvnc_lib, "WaitForMessage");
|
||||||
|
*(void**) (&HandleRFBServerMessage_f) = dlsym(libvnc_lib, "HandleRFBServerMessage");
|
||||||
|
}
|
||||||
|
|
||||||
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
|
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
|
||||||
VncPrivateData *data = (VncPrivateData *)rfbClientGetClientData(rfb, &TAG_0);
|
VncPrivateData *data = (VncPrivateData *)(*rfbClientGetClientData_f)(rfb, &TAG_0);
|
||||||
data->buffer = rfb->frameBuffer;
|
data->buffer = rfb->frameBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* GetPasswordCallback(rfbClient* cl){
|
static char* GetPasswordCallback(rfbClient* cl){
|
||||||
return strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
|
return strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
|
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
|
||||||
|
@ -25,8 +53,8 @@ static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->userCredential.password = strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
|
c->userCredential.password = strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_1));
|
||||||
c->userCredential.username = strdup((const char *)rfbClientGetClientData(cl, &TAG_2));
|
c->userCredential.username = strdup((const char *)(*rfbClientGetClientData_f)(cl, &TAG_2));
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +122,12 @@ VncCamera::~VncCamera() {
|
||||||
|
|
||||||
void VncCamera::Initialise() {
|
void VncCamera::Initialise() {
|
||||||
Debug(2, "Initializing Client");
|
Debug(2, "Initializing Client");
|
||||||
mRfb = rfbGetClient(8, 3, 4);
|
bind_libvnc_symbols();
|
||||||
|
mRfb = (*rfbGetClient_f)(8, 3, 4);
|
||||||
|
|
||||||
rfbClientSetClientData(mRfb, &TAG_0, &mVncData);
|
(*rfbClientSetClientData_f)(mRfb, &TAG_0, &mVncData);
|
||||||
rfbClientSetClientData(mRfb, &TAG_1, (void *)mPass.c_str());
|
(*rfbClientSetClientData_f)(mRfb, &TAG_1, (void *)mPass.c_str());
|
||||||
rfbClientSetClientData(mRfb, &TAG_2, (void *)mUser.c_str());
|
(*rfbClientSetClientData_f)(mRfb, &TAG_2, (void *)mUser.c_str());
|
||||||
|
|
||||||
mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback;
|
mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback;
|
||||||
mRfb->GetPassword = GetPasswordCallback;
|
mRfb->GetPassword = GetPasswordCallback;
|
||||||
|
@ -107,14 +136,14 @@ void VncCamera::Initialise() {
|
||||||
mRfb->programName = "Zoneminder VNC Monitor";
|
mRfb->programName = "Zoneminder VNC Monitor";
|
||||||
mRfb->serverHost = strdup(mHost.c_str());
|
mRfb->serverHost = strdup(mHost.c_str());
|
||||||
mRfb->serverPort = atoi(mPort.c_str());
|
mRfb->serverPort = atoi(mPort.c_str());
|
||||||
rfbInitClient(mRfb, 0, nullptr);
|
(*rfbInitClient_f)(mRfb, 0, nullptr);
|
||||||
scale.init();
|
scale.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VncCamera::Terminate() {
|
void VncCamera::Terminate() {
|
||||||
if(mRfb->frameBuffer)
|
if(mRfb->frameBuffer)
|
||||||
free(mRfb->frameBuffer);
|
free(mRfb->frameBuffer);
|
||||||
rfbClientCleanup(mRfb);
|
(*rfbClientCleanup_f)(mRfb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +154,8 @@ int VncCamera::PrimeCapture() {
|
||||||
|
|
||||||
int VncCamera::PreCapture() {
|
int VncCamera::PreCapture() {
|
||||||
Debug(2, "PreCapture");
|
Debug(2, "PreCapture");
|
||||||
WaitForMessage(mRfb, 500);
|
(*WaitForMessage_f)(mRfb, 500);
|
||||||
rfbBool res = HandleRFBServerMessage(mRfb);
|
rfbBool res = (*HandleRFBServerMessage_f)(mRfb);
|
||||||
return res == TRUE ? 1 : -1 ;
|
return res == TRUE ? 1 : -1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -403,18 +403,36 @@ char *timeval_to_string( struct timeval tv ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UriDecode( const std::string &encoded ) {
|
std::string UriDecode( const std::string &encoded ) {
|
||||||
#ifdef HAVE_LIBCURL
|
char a, b;
|
||||||
CURL *curl = curl_easy_init();
|
const char *src = encoded.c_str();
|
||||||
int outlength;
|
std::string retbuf;
|
||||||
char *cres = curl_easy_unescape(curl, encoded.c_str(), encoded.length(), &outlength);
|
retbuf.resize(encoded.length() + 1);
|
||||||
std::string res(cres, cres + outlength);
|
char *dst = &retbuf[0];
|
||||||
curl_free(cres);
|
while (*src) {
|
||||||
curl_easy_cleanup(curl);
|
if ((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {
|
||||||
return res;
|
if (a >= 'a')
|
||||||
#else
|
a -= 'a'-'A';
|
||||||
Warning("ZM Compiled without LIBCURL. UriDecoding not implemented.");
|
if (a >= 'A')
|
||||||
return encoded;
|
a -= ('A' - 10);
|
||||||
#endif
|
else
|
||||||
|
a -= '0';
|
||||||
|
if (b >= 'a')
|
||||||
|
b -= 'a'-'A';
|
||||||
|
if (b >= 'A')
|
||||||
|
b -= ('A' - 10);
|
||||||
|
else
|
||||||
|
b -= '0';
|
||||||
|
*dst++ = 16*a+b;
|
||||||
|
src+=3;
|
||||||
|
} else if (*src == '+') {
|
||||||
|
*dst++ = ' ';
|
||||||
|
src++;
|
||||||
|
} else {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dst++ = '\0';
|
||||||
|
return retbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_toupper( std::string& str) {
|
void string_toupper( std::string& str) {
|
||||||
|
|
Loading…
Reference in New Issue