So I'm trying to get libsodium's sodium_crypto_box_seal and sodium_crypto_box_seal_open working but for some reason, the open is failing and I can't work out why.
So in all my trying to get this working, I have built a test system that a single PHP file that tests how it would work cross server.
<pre>
<?php
/*** Client Sending ***/
// saved argument
$remotePublic = "DXOCV4BU6ptxt2IwKZaP23S4CjLESfLE+ng1tMS3tg4=";
// create out key for this message
$key = sodium_crypto_box_keypair();
// encrypt our message using the remotePublic
$sealed = sodium_crypto_box_seal("This is a test", base64_decode($remotePublic));
$send = json_encode((object)array("pub" => base64_encode(sodium_crypto_box_publickey($key)), "msg" => base64_encode($sealed)));
echo "Sending : {$send} \r\n";
/*** Server Setup ***/
$payload = json_decode($send);
$apps =
array (
'test' =>
array (
'S' => 'lv/dT3YC+Am1MCllkHeA2r3D25HW0zPjRrqzR8sepv4=',
'P' => 'DXOCV4BU6ptxt2IwKZaP23S4CjLESfLE+ng1tMS3tg4=',
),
);
/*** Server Opening ***/
$msg = $payload->msg;
$key = sodium_crypto_box_keypair_from_secretkey_and_publickey(base64_decode($apps['test']['S']), base64_decode($apps['test']['P']));
$opened = sodium_crypto_box_seal_open(base64_decode($msg), $key);
echo "Opened : {$opened} \r\n";
/*** Server Responding ***/
$sealedResp = base64_encode(sodium_crypto_box_seal("We Got your message '{$opened}'", base64_decode($payload->pub)));
echo "Responding : {$sealedResp}\r\n";
/*** Client Receiving ***/
$received = sodium_crypto_box_seal_open(base64_decode($sealedResp), $key);
echo "Received : {$received}\r\n";
/*** Sanity Checking ***/
if($received == "We Got your message 'This is a test'"){
echo "Test Successfull.\r\n";
}else{
echo "Test Failed got '{$received}' is not \"We Got your message 'This is a test'\"\r\n";
}
?>
</pre>
Output is:
Sending : {"pub":"DS2uolF5lXZ1E3rw0V2WHELAKj6+vRKnxGPQFlhTEFU=","msg":"VVYfphc2RnQL2E8A0oOdc6E\/+iUgWO1rPd3rfodjLhE+slEWsivB6QiaLiMuQ31XMP\/1\/s+t+CSHu8QukoY="}
Opened : This is a test
Responding : cvDN9aT9Xj7DPRhYZFGOR4auFnAcI3qlwVBBRY4mN28JmagaR8ZR9gt6W5C0xyt06AdrQR+sZFcyb500rx6iDTEC4n/H77cUM81vy2WfV8m5iRgp
Received :
Test Failed got '' is not "We Got your message 'This is a test'"
There's two problems here.
First -- in this step under "Server Opening":
$opened = sodium_crypto_box_seal_open($msg, $key);
$msg is still Base64 encoded, so trying to decrypt it will fail.
Second -- the public key that is included in the "pub" field of $send is the public key of a random keypair that was generated by sodium_crypto_box_keypair(), not the same public key as $remotePublic or the pair in $apps. This key is overwritten by a call to sodium_crypto_box_keypair_from_secretkey_and_publickey() later in the application, making the original message unrecoverable.
Related
I'm trying to send messages to multiple recipients with different message body but I don't know if my script has any error. The problem is when I execute this below code, only one user email will receive message. If I try it again another one will get a message. I want all the emails in the array to receive the message with individual message body. And also I noticed that my script takes long to complete execution. Is there a better way to get this working as expected?
PHP
<?php
$conn_handler->prepare('
SELECT * FROM food_orders fo
INNER JOIN our_chefs oc
ON oc.chef_private_key = fo.order_chefpkey
WHERE fo.order_id = :currentorder AND fo.order_userid = :order_userid
ORDER BY fo.order_chefpkey
');
$conn_handler->bind(':currentorder', $lastOrderId);
$conn_handler->bind(':order_userid', $buyerid);
$conn_handler->execute();
$getFoodOrders = $conn_handler->getAll();
if( !isset($_SESSION['completed_'.$lastOrderId]) ) {
$creatProducts = array();
$email_list = array();
/*Here i loop on current orders*/
foreach($getFoodOrders as $row) {
//Create an array of chef emails
$email_list[$row->chef_private_key] = $row->chef_email;
//Create an array of items based on chef private key
$creatProducts[$row->order_chefpkey][] = array(
'o_name' => $row->order_foodname,
'o_pid' => $row->oder_foodid,
'o_price' => $row->order_price,
'o_currency' => $row->currency,
'o_qty' => $row->order_qty,
'o_size' => $row->order_size,
'o_img' => $row->order_image,
);
}
//Here i loop through the above chef emails
foreach($email_list as $key => $val) {
$productBuilder = null;
//Here i create html for products based on chef keys
foreach($creatProducts[$key] as $erow) {
$productBuilder .= '<div><b>Product Name:</b> '.$erow['o_name'].'<br/></div>';
}
//Here i send email to each chef with their individual products created above
$sourcejail->sendMail(
$val, //Send TO
null, //Send Bcc
null, //Send CC
null, //reply To
1, //Something
'Your have received new order ('.$lastOrderId.')', //Subject
$productBuilder //Message body
);
}
$_SESSION['completed_'.$lastOrderId] = true;
}
I am using PHP with XAMPP and Dialogflow to create a chat interface. In a simple intent(question) in Dialogflow, I have created a webhook to XAMPP regarding the question 'Who is X' (e.g. Paul, George). Therefore , I place a POST REQUEST in order to have access to the json form of this question in DIalogflow so that I can answer it as I want to. Specifically, the ultimate goal of this is to retrieve some data from a MySQL database in phpMyAdmin about this question and respond for example that 'X is a developer' or 'X is a financial analyst'. This is why wrote a php script which is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
// Process when it is POST method
if ($method == 'POST') {
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->result->parameters;
switch($text) {
case 'given-name':
$name = $text->given-name;
$speech = $name . 'is a developer';
break;
default:
$speech = 'Sorry I did not get this. Can you repeat please?';
}
$response = new \stdClass();
$response->speech = "";
$response->displayText = "";
$respone->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
However, the output of this program is: Method not allowed.
Paradoxically enough $method has the value 'GET' so it identifies a GET REQUEST while Dialogflow explicitly states at the webhook page that
Your web service will receive a POST request from Dialogflow in the
form of the response to a user query matched by intents with webhook
enabled.
Hence I am wondering: why my php script cannot see and process the POST REQUEST from Dialogflow?
P.S. Questions close to mine are the following: Form sends GET instead of POST, Why is $_SERVER['REQUEST_METHOD'] always GET?.
It doesn't work because $_SERVER['REQUEST_METHOD'] == "GET" by default.
So you program execute the 'else' condition.
You need to submit a request with the POST method to change this value.
You can use
<form method="POST">
[...]
</form>
in your HTML, or
$.ajax({
url : "ajax_url.php",
type : 'POST',
data : 'data='+data,
[...]
});
in your AJAX JS code for example
Here i am doing same like you from below code your Query will be resolved,
index.php
<?php
require 'get_enews.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'getNews':
$param = $input["result"]["parameters"]["number"];
getNews($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_enews.php
<?php
function getNews($param){
require 'config.php';
$getNews="";
$Query="SELECT link FROM public.news WHERE year='$param'";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$getNews= "Here is details that you require - Link: " . $row["link"];
$arr=array(
"source" => "RMC",
"speech" => $getNews,
"displayText" => $getNews,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "No year matched in database.",
"displayText" => "No year matched in database.",
);
sendMessage($arr);
}
}
?>
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input
My code is working when I am using a direct internet (open network). but when I tried to use a private network (which i am currently using in my company) I am getting this error.
Warning: Invalid argument supplied for foreach() in E:\Files\xampp\xampp\htdocs\nexmo\src\NexmoMessage.php on line 228
Below is my code for sending the message..
<?php
include ( "src/NexmoMessage.php" );
if(isset($_POST['sendMessage'])){
$to = $_POST['to'];
$message = $_POST['smsMessage'];
// Step 1: Declare new NexmoMessage.
$nexmo_sms = new NexmoMessage('xxxxxxxx', 'xxxxxxxxx');
// Step 2: Use sendText( $to, $from, $message ) method to send a message.
$info = $nexmo_sms->sendText( $to, 'NexmoWorks', $message );
// Step 3: Display an overview of the message
//echo $nexmo_sms->displayOverview($info);
// Done!
}
?>
and below is the code where i am having an error.
foreach($obj as $key => $val){
// If we come across another class/array, normalise it
if ($val instanceof stdClass || is_array($val)) {
$val = $this->normaliseKeys($val);
}
// Replace any unwanted characters in they key name
if ($is_obj) {
$new_obj->{str_replace('-', '', $key)} = $val;
} else {
$new_obj[str_replace('-', '', $key)] = $val;
}
}
I use the LINE BOT API Trial SDK PHP (https://github.com/line/line-bot-sdk-php).
But, for this method:
$res = $bot->sendText(['TARGET_MID'], 'Message');
How to get the user's MID to send them a message?
Thanks for help.
1) A very quick way to get the mid of an interactive user (more of a fun hack, really) is to register a callback URL as per the API instructions, then capture the POST data to that URL like so:
// /callback/index.php
<?php
$postdata = file_get_contents("php://input");
#file_get_contents('https://'.$_SERVER['SERVER_NAME'].'/LINE/' . json_encode($postdata));
Next, scan the QR code in the channel console and add your trial bot to your LINE account. After that is done, send it a quick "Hello!" text.
You could then save the POST data to a text file if you wish, or you could check the server logs. For example, you might see something like this:
163.128.118.223 - - [03/Sep/2016:07:25:25 -0700] "POST /line/callback/ HTTP/1.1" 200 - "-" "ChannelEventDispatcher/1.0"
106.152.218.107 - - [03/Sep/2016:07:25:25 -0700] "GET /LINE/{\"result\":[{\"content\":{\"toType\":1,\"createdTime\":1472114754839,\"from\":\"ub7dbd4a12c322f6c0117773d739c55a4\",\"location\":null,\"id\":\"4357194057879\",\"to\":[\"u2b6a4ba287028dee7291122094dac827\"],\"text\":\"Hello!\",\"contentMetadata\":{\"AT_RECV_MODE\":\"2\",\"SKIP_BADGE_COUNT\":\"true\"},\"deliveredTime\":0,\"contentType\":1,\"seq\":null},\"createdTime\":1472912724868,\"eventType\":\"138311609000106301\",\"from\":\"u236d23c2e36bd87217655609a1c31cb8\",\"fromChannel\":1241102815,\"id\":\"WB1519-3102846635\",\"to\":[\"u2b6a4ba287028dee7291122094dac827\"],\"toChannel\":1462261375}]} HTTP/1.1" 404 15 "-" "-"
The \"from\":\"ub7dbd4a12c322f6c0117773d739c55a4\" is the pertinent part.
2) If you'd like to get started with receiving messages, you can start like this as your callback script. Simply send your BOT the message 'mid' and it should respond with your mid.
Here is a starting callback script I made with signature verification included for you.
// /callback/index.php
<?php
// Show all errors for testing
error_reporting(E_ALL);
// SDK is installed via composer
require_once __DIR__ . "/includes/vendor/autoload.php";
use LINE\LINEBot;
use LINE\LINEBot\HTTPClient\GuzzleHTTPClient;
// Set these
$config = [
'channelId' => LINE_CHANNEL_ID,
'channelSecret' => LINE_CHANNEL_SECRET,
'channelMid' => LINE_CHANNEL_MID,
];
$sdk = new LINEBot($config, new GuzzleHTTPClient($config));
$postdata = #file_get_contents("php://input");
$messages = $sdk->createReceivesFromJSON($postdata);
// Verify the signature
// REF: http://line.github.io/line-bot-api-doc/en/api/callback/post.html#signature-verification
$sigheader = 'X-LINE-ChannelSignature';
// REF: http://stackoverflow.com/a/541450
$signature = #$_SERVER[ 'HTTP_'.strtoupper(str_replace('-','_',$sigheader)) ];
if($signature && $sdk->validateSignature($postdata, $signature)) {
// Next, extract the messages
if(is_array($messages)) {
foreach ($messages as $message) {
if ($message instanceof LINEBot\Receive\Message\Text) {
$text = $message->getText();
if ($text == "mid") {
$fromMid = $message->getFromMid();
// Send the mid back to the sender and check if the message was delivered
$result = $sdk->sendText([$fromMid], 'mid: ' . $fromMid);
if(!$result instanceof LINE\LINEBot\Response\SucceededResponse) {
error_log('LINE error: ' . json_encode($result));
}
} else {
// Process normally, or do nothing
}
} else {
// Process other types of LINE messages like image, video, sticker, etc.
}
}
} // Else, error
} else {
error_log('LINE signatures didn\'t match');
}
I'm new to using EWS from Exchangeclient classes.
I'm looking for a simple example how to send an email with an attachment. I've found examples about how to send an email but not sending an email with an attachment.
This is my script:
$exchangeclient = new Exchangeclient();
$exchangeclient->init($username, $password, NULL, 'ews/Services.wsdl');
$exchangeclient->send_message($mail_from, $subject, $body, 'HTML', true, true);
I have the following soap request.
$CreateItem->MessageDisposition = "SendAndSaveCopy";
$CreateItem->SavedItemFolderId->DistinguishedFolderId->Id = "sentitems";
$CreateItem->Items->Message->ItemClass = "IPM.Note";
$CreateItem->Items->Message->Subject = $subject;
$CreateItem->Items->Message->Body->BodyType = $bodytype;
$CreateItem->Items->Message->Body->_ = $content;
$CreateItem->Items->Message->ToRecipients->Mailbox->EmailAddress = $to;
$CreateItem->Items->Message->Attachments->FileAttachment->AttachmentId = $attach['AttachmentId'];
$CreateItem->Items->Message->Attachments->FileAttachment->Name = $attach['Name'];
$CreateItem->Items->Message->Attachments->FileAttachment->ContentType = $attach['ContentType'];
$CreateItem->Items->Message->Attachments->FileAttachment->ContentId = $attach['AttachmentId'];
$CreateItem->Items->Message->Attachments->FileAttachment->Content = $attach['ContentId'];
$CreateItem->Items->Message->Attachments->FileAttachment->Size = $attach['Size'];
The error I am getting is:
Fatal error: Uncaught SoapFault exception: [a:ErrorSchemaValidation] The request failed schema validation: The required attribute 'Id' is missing.
In order to send email with an attachment you have to first create the Message (Item) without any recipients (and a MessageDisposition of "SendToNone" or something like that) and save it in your Drafts folder. THEN create a request for a CreateAttachment, like so, where $key is the changekey of the item you created earlier (you have to read back the server response and save the changekey somewhere, because the changekey changes for an item with every modification it undergoes):
$attachrequest->ParentItemId->ChangeKey = $key;
$attachrequest->Attachments->FileAttachment->Name = $attachment_name;
$attachrequest->Attachments->FileAttachment->ContentLocation = $attachment;
$attachrequest->Attachments->FileAttachment->Content = $attachment_content;
$attachrequest->Attachments->FileAttachment->ContentType = $attachment_contenttype;
$response = self::$ews->CreateAttachment($attachrequest);
THEN you update the message (with an UpdateItem) to include recipients and so that the MessageDisposition is something like SendToAllAndSaveCopy.
(Disclaimer: I'm using this method now and it's all working fine, except for identifying the right format for Attachments->FileAttachment->Content, which looks like it should be the encoded base64 data of the attachment--but my computer can't open the attachments I'm sending.)
At any rate I believe this is the way to do it, and certainly I have been able to send messages with attachments with it.