mirror of https://github.com/SeanOMik/znc-push.git
Add support for using curl instead of CSocket
When compiling with USE_CURL defined, znc push will use libcurl for making http requests instead of ZNC's builtin CSocket library. This enables some advanced features, such as supporting HTTP proxies for outbound requests. Currently, building with curl support requires running the following: make curl=yes clean install libcurl must already be installed and accessible by default. Otherwise, it is up to the user to populate CXXFLAGS with the appropriate values so that znc-buildmod can appropriately find and link libcurl to the module.
This commit is contained in:
parent
103933f492
commit
77ce3e8c1a
9
Makefile
9
Makefile
|
@ -1,8 +1,15 @@
|
|||
version := $(shell git describe --dirty)
|
||||
curl=no
|
||||
|
||||
ifneq ($(curl),no)
|
||||
flags=-DUSE_CURL -lcurl
|
||||
else
|
||||
flags=
|
||||
endif
|
||||
|
||||
push.so: push.cpp
|
||||
sed -i -e "s|PUSHVERSION \".*\"|PUSHVERSION \"$(version)\"|" push.cpp
|
||||
znc-buildmod push.cpp
|
||||
CXXFLAGS="$(CXXFLAGS) $(flags)" znc-buildmod push.cpp
|
||||
sed -i -e "s|PUSHVERSION \".*\"|PUSHVERSION \"dev\"|" push.cpp
|
||||
|
||||
install: push.so
|
||||
|
|
10
README.md
10
README.md
|
@ -50,6 +50,16 @@ Otherwise, run the full command:
|
|||
$ znc-buildmod push.cpp
|
||||
|
||||
|
||||
### Advanced
|
||||
|
||||
If you would like to compile ZNC Push using libcurl for http requests, you must use:
|
||||
|
||||
$ make curl=yes
|
||||
|
||||
If libcurl is not in the default system library paths, you will need to populate `$CXXFLAGS`
|
||||
with the appropriate GCC flags so that it can find and link ZNC Push with libcurl.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
|
|
136
push.cpp
136
push.cpp
|
@ -21,9 +21,25 @@
|
|||
#include "time.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_CURL
|
||||
#include <curl/curl.h>
|
||||
#endif // USE_CURL
|
||||
|
||||
// Forward declaration
|
||||
class CPushMod;
|
||||
|
||||
/**
|
||||
* Shorthand for encoding a string for a URL.
|
||||
*
|
||||
* @param str String to be encoded
|
||||
* @return Encoded string
|
||||
*/
|
||||
CString urlencode(const CString& str)
|
||||
{
|
||||
return str.Escape_n(CString::EASCII, CString::EURL);
|
||||
}
|
||||
|
||||
#ifndef USE_CURL
|
||||
/**
|
||||
* Socket class for generating HTTP requests.
|
||||
*/
|
||||
|
@ -54,17 +70,13 @@ class CPushSocket : public CSocket
|
|||
// User agent to use
|
||||
CString user_agent;
|
||||
|
||||
/**
|
||||
* Shorthand for encoding a string for a URL.
|
||||
*
|
||||
* @param str String to be encoded
|
||||
* @return Encoded string
|
||||
*/
|
||||
CString urlencode(const CString& str)
|
||||
{
|
||||
return str.Escape_n(CString::EASCII, CString::EURL);
|
||||
}
|
||||
};
|
||||
#else
|
||||
// forward declaration
|
||||
CURLcode make_curl_request(const CString& service_host, const CString& service_url,
|
||||
const CString& service_auth, MCString& params, int port,
|
||||
bool use_ssl, bool use_post);
|
||||
#endif // USE_CURL
|
||||
|
||||
/**
|
||||
* Push notification module.
|
||||
|
@ -98,6 +110,10 @@ class CPushMod : public CModule
|
|||
public:
|
||||
|
||||
MODCONSTRUCTOR(CPushMod) {
|
||||
#ifdef USE_CURL
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
#endif
|
||||
|
||||
app = "ZNC";
|
||||
|
||||
idle_time = time(NULL);
|
||||
|
@ -135,7 +151,12 @@ class CPushMod : public CModule
|
|||
defaults["query_conditions"] = "all";
|
||||
defaults["debug"] = "off";
|
||||
}
|
||||
virtual ~CPushMod() {}
|
||||
|
||||
virtual ~CPushMod() {
|
||||
#ifdef USE_CURL
|
||||
curl_global_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
@ -441,11 +462,15 @@ class CPushMod : public CModule
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_CURL
|
||||
make_curl_request(service_host, service_url, service_auth, params, use_port, use_ssl, use_post);
|
||||
#else
|
||||
// Create the socket connection, write to it, and add it to the queue
|
||||
CPushSocket *sock = new CPushSocket(this);
|
||||
sock->Connect(service_host, use_port, use_ssl);
|
||||
sock->Request(use_post, service_host, service_url, params, service_auth);
|
||||
AddSocket(sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1380,11 +1405,15 @@ class CPushMod : public CModule
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_CURL
|
||||
make_curl_request(service_host, service_url, service_auth, params, use_port, use_ssl, use_post);
|
||||
#else
|
||||
// Create the socket connection, write to it, and add it to the queue
|
||||
CPushSocket *sock = new CPushSocket(this);
|
||||
sock->Connect(service_host, use_port, use_ssl);
|
||||
sock->Request(use_post, service_host, service_url, params, service_auth);
|
||||
AddSocket(sock);
|
||||
#endif
|
||||
|
||||
PutModule("Ok");
|
||||
}
|
||||
|
@ -1420,24 +1449,18 @@ class CPushMod : public CModule
|
|||
};
|
||||
|
||||
/**
|
||||
* Send an HTTP request.
|
||||
* Build a query string from a dictionary of request parameters.
|
||||
*
|
||||
* @param post POST command
|
||||
* @param host Host domain
|
||||
* @param url Resource path
|
||||
* @param parameters Query parameters
|
||||
* @param auth Basic authentication string
|
||||
* @param params Request parameters
|
||||
* @return query string
|
||||
*/
|
||||
void CPushSocket::Request(bool post, const CString& host, const CString& url, MCString& parameters, const CString& auth)
|
||||
CString build_query_string(MCString& params)
|
||||
{
|
||||
parent->PutDebug("Building notification to " + host + url + "...");
|
||||
|
||||
// query string for the request
|
||||
bool more = false;
|
||||
CString query;
|
||||
CString key;
|
||||
CString value;
|
||||
for (MCString::iterator param = parameters.begin(); param != parameters.end(); param++)
|
||||
for (MCString::iterator param = params.begin(); param != params.end(); param++)
|
||||
{
|
||||
key = urlencode(param->first);
|
||||
value = urlencode(param->second);
|
||||
|
@ -1453,6 +1476,74 @@ void CPushSocket::Request(bool post, const CString& host, const CString& url, MC
|
|||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
#ifdef USE_CURL
|
||||
/**
|
||||
* Send an HTTP request using libcurl.
|
||||
*
|
||||
* @param service_host Host domain
|
||||
* @param service_url Host path
|
||||
* @param service_auth Basic auth string
|
||||
* @param params Request parameters
|
||||
* @param port Port number
|
||||
* @param use_ssl Use SSL
|
||||
* @param use_post Use POST method
|
||||
*/
|
||||
CURLcode make_curl_request(const CString& service_host, const CString& service_url,
|
||||
const CString& service_auth, MCString& params, int port,
|
||||
bool use_ssl, bool use_post)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode result;
|
||||
|
||||
curl = curl_easy_init();
|
||||
|
||||
CString url = CString(use_ssl ? "https" : "http") + "://" + service_host + service_url;
|
||||
CString query = build_query_string(params);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.data());
|
||||
curl_easy_setopt(curl, CURLOPT_PORT, port);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ZNC Push");
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); // three seconds ought to be good enough for anyone, eh?
|
||||
|
||||
if (service_auth != "")
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, service_auth.data());
|
||||
}
|
||||
|
||||
if (use_post)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query.data());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, query.length());
|
||||
}
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Send an HTTP request.
|
||||
*
|
||||
* @param post POST command
|
||||
* @param host Host domain
|
||||
* @param url Resource path
|
||||
* @param parameters Query parameters
|
||||
* @param auth Basic authentication string
|
||||
*/
|
||||
void CPushSocket::Request(bool post, const CString& host, const CString& url, MCString& parameters, const CString& auth)
|
||||
{
|
||||
parent->PutDebug("Building notification to " + host + url + "...");
|
||||
|
||||
CString query = build_query_string(parameters);
|
||||
|
||||
parent->PutDebug("Query string: " + query);
|
||||
|
||||
// Request headers and POST body
|
||||
|
@ -1514,5 +1605,6 @@ void CPushSocket::Disconnected()
|
|||
parent->PutDebug("Disconnected.");
|
||||
Close(CSocket::CLT_AFTERWRITE);
|
||||
}
|
||||
#endif // USE_CURL
|
||||
|
||||
MODULEDEFS(CPushMod, "Send highlights and personal messages to a push notification service")
|
||||
|
|
Loading…
Reference in New Issue