Sending feedback data via HTTPS POST from wxWidgets application - http

I have a wxWidgets application and would like to add a way for users to submit feedback in a simple (implementation and usage), reliable, cross-platform and secure way. Using HTTP POST over SSL seems to fit those requirements best (although I'll consider answers that suggest other approaches). However, support for HTTPS in wxWidgets seems limited.
Here are some of the options I've considered and the problems with them:
wxSMTP: no SSL/TLS support that I've found. Relies on user having a correct mail configuration (sendmail, MAPI).
wxHTTP: everything but SSL/HTTPS support.
wxSSL: everything if it wasn't incomplete and long dead.
wxCURL: everything but complicated to build/incorporate (in fact currently release fails to build).
libcurl: just link with and call into libcurl directly. This is the solution I've settled on (and I have a working prototype) but it feels very non-wx and while libcurl is cross-platform, Windows is definitely not its native platform so it adds significant dependency and build complexity to the project.

I've decided to go with libCURL linked to openssl. Both of the packages are able availabe on most Linux system and can be fairly easily built on Windows and OS X.
Here is example C code that sends feedback:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
/* Fill in the name field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "name",
CURLFORM_COPYCONTENTS, "John Doe",
CURLFORM_END);
/* Fill in the comments field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "comments",
CURLFORM_COPYCONTENTS, "using HTTPS POST\nline 2\nline 3",
CURLFORM_END);
curl = curl_easy_init();
/* initalize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL,
"https://some_host.com/path/feedback.php");
// Uncomment to disable certificate checks
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
printf("Curl result: %d\n", res);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
return 0;
}
That can be compiled on Linux like so:
gcc post.c -lcurl -o post
Here is example PHP code that accepts that post:
<?php
$recipient = "john#some_host.com";
if (empty($_POST)) {
// We only accpet POSTs
header('HTTP/1.0 403 Forbidden');
exit;
} else {
// Handle a POST
$message .= "Submitted at ".date("F j, Y, g:i a")."\n\n";
$message .= "Name:\n";
$message .= $_POST['name']."\n\n";
$message .= "-------------------------------------------\n\n";
$message .= "Comments:\n\n";
$message .= $_POST['comments']."\n\n";
// Send message to email address
$sent = mail($recipient, "Feedback",
$message, "From: Feedback <noreply#some_host.com>\r\n");
if ($sent) {
?>
<html>
<body>
Got POST and sent email:
<pre><? echo $message; ?></pre>
</body>
</html>
<?php
} else {
// Return an error
header('HTTP/1.0 500 Internal Server Error', true, 500);
exit;
}
}
?>

Boost::Asio is an alternative I've used before, even in a wxWidgets app. I've used it to download files before (and only have sample code for that), but sadly don't have (and can't quickly find) sample code for HTTP(S) POSTs.
Boost::asio has a "problem" in that it's Boost (which is either a big problem because "ugh, Boost", or not a problem "Awesome, Boost!"

Related

Updating a WooCommerce order status based on a $GET response?

I tried to look things up but I am unable to find anything quite similar.
So I have an external file. That file uses $_GET in order to enable bidirectional text order confirmations.
I am trying to modify order status based on that specific $_GET response, but I am now unable to generate any sort of error in my error logs and cannot quite tell what I am doing wrong. Please bear with me as I am not very experience with this.
Here's what I have done so far:
<?php
define( 'WP_USE_THEMES', false );
require_once( $_SERVER[ 'DOCUMENT_ROOT' ] . '/wp-load.php' );
/*
Receiving SMS using 2-Way SMS & PHP
if ((isset($_GET["sender"])) and
(isset($_GET["receiver"])) and
(isset($_GET["message"])) and
(isset($_GET["timestamp"])) and
(isset($_GET["network_id"])) and
(isset($_GET["network_name"]))
)
{
/*
The Sender of the SMS (ie. 07xyzzzzzz)
*/
$sender = $_GET["sender"];
/*
The Shortcode on which the SMS was sent (ie. 17xy, 18xy, 37xy, 38xy etc.)
*/
$receiver = $_GET["receiver"];
/*
The Message sent by the Sender to the Shortcode
*/
$message = $_GET["message"];
/*
The Timestamp in which the Message was received on the Shortcode, in UNIX Timestamp format.
*/
$timestamp = $_GET["timestamp"];
/*
The Network ID in which the Sender is located, with the following possible values:
1 for Vodafone Romania
2 for Orange Romania
3 for Telekom Romania Mobile / Telekom Romania
5 for Digimobil (RCS-RDS)
*/
$network_id = $_GET["network_id"];
/*
The Network Name corresponding to the Network ID
*/
$network_name = $_GET["network_name"];
/*
Write the SMS received to a text file
Please note that this is for example purpose only and the file(s) below must be not be publicly accessible. If you will
choose to store the SMS received to file(s) you must enable access restrictions and deny access from public to the respective
file(s) and you must disable directory listing on the directory where the files are stored.
We recommend you storing the SMS received to a database.
$handler = fopen("sms-mobile-originated-".date("d-m-Y", $timestamp)."txt", "a+");
fwrite($handler,
"SMS Received: From ".$sender.", ".
"Receiver ".$receiver.", ".
"Network ID: ".$network_id.", ".
"Network Name: ".$network_name.", ".
"Date / Time: ".date("d-m-Y H:i:s", $timestamp).", ".
"Message: ".$message.
"\r\n"
);
fclose($handler);
/*
Return the response to the request
For each received SMS you may send a SMS response to the sender (mobile subscriber) using any of the following methods:
(1) Using SMSLink - SMS Gateway API, such as SMS Gateway (HTTP), SMS Gateway (SOAP), SMS Gateway (JSON) or SMS Gateway (BULK)
(2) Using the output of this script, by writing the desired response below, if you enable this coresponding option in 2-Way SMS,
2-Way SMS Campaigns - Settings. In this case the SMSLink will read the script output and will send an SMS to the sender with
the output text. Please note that the output should be plain text (you should not output any HTML code).
*/
function sms_confirmation(){
if (substr(trim(urldecode($message)), 0, strlen("CF ETIN")) == "CF ETIN")
{
global $woocommerce;
$order = new WC_Order($order_id);
$phone = $order->get_billing_phone();
if (((strlen($phone) == 10) and ($phone == $sender)) or
((strlen($phone) == 9) and ("0".$phone == $sender)) or
((strlen($phone) == 11) and ($phone == "4".$sender)) or
((strlen($phone) == 13) and ($phone == "004".$sender)) or
((strlen($phone) == 12) and ($phone == "+4".$sender))
)
{
$order->update_status('confirm-sms', __('Approved by the customer', 'woocommerce') );
}
}
};
echo "Message Successfuly Received."
}
else
{
echo "Invalid Request.";
}
?>

libcURL get request

pretty useless at code but I can but try.
I'm trying to send a HTTP request [GET] via localhost to a radio sever program. [Windows C++]
I can send this from my browser or cmd and the result is volume is set to zero
http://127.0.0.1:8282/parameter/hd1/spk/volume?set=0
I can connect with my c++ app, tried both winsock & libcURL. But the volume does not change
this is pretty much the example from cURL, I'm trying the smallest incremental steps I can.
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL* curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1:8282");
curl_easy_setopt(curl, CURLOPT_HTTPGET, "/parameter/hd1/spk/volume?=0");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
EDIT
This is ridiculous, but this did it, removed the CURLOPT_HTTPGET bit, and put the full path in CURLOPT_URL,
it's not supposed to work like that is it?
curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1:8282/parameter/hd1/spk/volume?=0");

How to return binary data from custom wordpress rest api endpoint

I am writing a custom endpoint for a REST api in wordpress, following the guide here: https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
I am able to write a endpoint that returns json data. But how can I write an endpoint that returns binary data (pdf, png, and similar)?
My restpoint function returns a WP_REST_Response (or WP_Error in case of error).
But I do not see what I should return if I want to responde with binary data.
Late to the party, but I feel the accepted answer does not really answer the question, and Google found this question when I searched for the same solution, so here is how I eventually solved the same problem (i.e. avoiding to use WP_REST_Response and killing the PHP script before WP tried to send anything else other than my binary data).
function download(WP_REST_Request $request) {
$dir = $request->get_param("dir");
// The following is for security, but my implementation is out
// of scope for this answer. You should either skip this line if
// you trust your client, or implement it the way you need it.
$dir = sanitize_path($dir);
$file = $request->get_param("file");
// See above...
$file = sanitize_path($file);
$sandbox = "/some/path/with/shared/files";
// full path to the file
$path = $sandbox.$dir.$file;
$name = basename($path);
// get the file mime type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $path);
// tell the browser what it's about to receive
header("Content-Disposition: attachment; filename=$name;");
header("Content-Type: $mime_type");
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header('Content-Length: ' . filesize($path));
header("Cache-Control: no-cache private");
// stream the file without loading it into RAM completely
$fp = fopen($path, 'rb');
fpassthru($fp);
// kill WP
exit;
}
I would look at something called DOMPDF. In short, it streams any HTML DOM straight to the browser.
We use it to generate live copies of invoices straight from the woo admin, generate brochures based on $wp_query results etc. Anything that can be rendered by a browser can be streamed via DOMPDF.

Wordpress Mixed content requested an insecure XMLHttpRequest endpoint

OK I checked all other similar answers, but thanks to people that downvote for no reason there is no actual response.
I am using Wordpress and I have a Mixed Content with a website https://oujdaportail.net/
It is generating this error:
Mixed Content: The page at 'https://oujdaportail.net/' was loaded over
HTTPS, but requested an insecure XMLHttpRequest endpoint
'http://oujdaportail.net/'. This request has been blocked; the content
must be served over HTTPS.
Chrome debug console has been completely useless!! It detects the error at the first line of source code where there is nothing to look up.
I am not sure how I should resolve this... I need help to capture the source of this issue.
Finally! I would be someone's hero...
After hours of struggle, it turned out that wp_head and wp_footer where responsible for generating unknown HTTP requests. And to fix it all I had to do is create a custom wp_head and wp_footer function just like this:
/**
* Wrapper for wp_head() which manages SSL
*
* #uses wp_head()
* #param bool $ssl
* #return void
*/
function custom_wp_head() {
// Capture wp_head output with buffering
ob_start();
wp_head();
$wp_head = ob_get_contents();
ob_end_clean();
// Replace plain protocols
$wp_head = preg_replace( '/(["\'])http:\/\//', '\1https://', $wp_head );
// Output
echo $wp_head;
}
function custom_wp_footer() {
// Capture wp_head output with buffering
ob_start();
wp_footer();
$wp_footer = ob_get_contents();
ob_end_clean();
// Replace plain protocols
$wp_footer = preg_replace( '/(["\'])http:\/\//', '\1https://', $wp_footer );
// Output
echo $wp_footer;
}

libcurl: write call back function not invoked

I am using libcurl to send a POST request, and am trying to get response using the callback function. Below is the relevant code.
main ()
{
...
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init ();
curl_easy_setopt(curl, CURLOPT_URL, url_string);
curl_easy_setopt(curl, CURLOPT_POST, 1);
if (strlen(query_string) > 0)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query_string);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_buffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCB);
CURLcode res = curl_easy_perform(curl);
if (CURLE_OK == res)
printf("response: %s\n", write_buffer.data);
else
printf("curl failed\n");
curl_easy_cleanup(curl);
curl_global_cleanup();
...
}
struct BufferType
{
Str data;
BufferType() {};
size_t Append(char *src, size_t size, size_t nmemb)
{
data.Append(Str(src, size * nmemb));
return size * nmemb;
}
};
size_t WriteCB(char *data, size_t size, size_t nmemb, BufferType *buffer)
{
printf("WriteCB: %s\n", data);
fflush(stdout);
return buffer->Append(data, size, nmemb);
}
When I launched the program, I can see it is executed (the server responds with "200 OK"). But the program just hangs there, here is the output:
WriteCB: HTTP/1.1 100 Continue
WriteCB:
More info: if I use GET method for other URL, and change the two lines related to POST to
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
Then the code works fine.
What could be wrong?
SOLVED
In the command line, I let the user to specify query string, and I have a statement such that if the "query_string" is empty then do not call
"curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query_string);".
Setting curl to verbose shows that the request header has "Expect: 100-continue". So I guess it is because the query string is not set yet. Even it is empty, it should be set.
Glad you found the issue. I originally though you might not be using POST correctly with libcurl which is easy to do. So, I tried your code but didn't find any issue with it.
So, it had to be either an issue with the how you were setting it up or the server itself. The callbacks were behaving as expected. I wanted to try it out because I generally use POST with libcurl like this:
struct curl_httppost* post = NULL;
struct curl_httppost* last = NULL;
curl_formadd(&post, &last, ..., CURLFORM_END);
Here is an example

Resources